diff --git a/api/server/router/grpc/grpc.go b/api/server/router/grpc/grpc.go index 939953f7b4..f21bce53ed 100644 --- a/api/server/router/grpc/grpc.go +++ b/api/server/router/grpc/grpc.go @@ -9,7 +9,7 @@ import ( "os" "strings" - "github.com/containerd/containerd/defaults" + "github.com/containerd/containerd/v2/defaults" "github.com/containerd/log" "github.com/docker/docker/api/server/router" "github.com/docker/docker/internal/otelutil" diff --git a/builder/builder-next/adapters/containerimage/pull.go b/builder/builder-next/adapters/containerimage/pull.go index 79f84c6e6f..3815ff5e34 100644 --- a/builder/builder-next/adapters/containerimage/pull.go +++ b/builder/builder-next/adapters/containerimage/pull.go @@ -14,15 +14,15 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/gc" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - cdreference "github.com/containerd/containerd/reference" - ctdreference "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/containerd/containerd/remotes/docker/schema1" is deprecated: use images formatted in Docker Image Manifest v2, Schema 2, or OCI Image Spec v1. + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019: "github.com/containerd/containerd/remotes/docker/schema1" is deprecated: use images formatted in Docker Image Manifest v2, Schema 2, or OCI Image Spec v1. + "github.com/containerd/containerd/v2/pkg/gc" + cdreference "github.com/containerd/containerd/v2/pkg/reference" + ctdreference "github.com/containerd/containerd/v2/pkg/reference" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" @@ -524,7 +524,11 @@ func (p *puller) Snapshot(ctx context.Context, g session.Group) (cache.Immutable handlers []c8dimages.Handler ) if p.desc.MediaType == c8dimages.MediaTypeDockerSchema1Manifest { - schema1Converter = schema1.NewConverter(p.is.ContentStore, fetcher) + schema1Converter, err = schema1.NewConverter(p.is.ContentStore, fetcher) + if err != nil { + stopProgress() + return nil, err + } handlers = append(handlers, schema1Converter) // TODO: Optimize to do dispatch and integrate pulling with download manager, diff --git a/builder/builder-next/adapters/localinlinecache/inlinecache.go b/builder/builder-next/adapters/localinlinecache/inlinecache.go index 8cb0bfb3ce..fa961ece5f 100644 --- a/builder/builder-next/adapters/localinlinecache/inlinecache.go +++ b/builder/builder-next/adapters/localinlinecache/inlinecache.go @@ -5,9 +5,9 @@ import ( "encoding/json" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes/docker" distreference "github.com/distribution/reference" imagestore "github.com/docker/docker/image" "github.com/docker/docker/reference" diff --git a/builder/builder-next/adapters/snapshot/leasemanager.go b/builder/builder-next/adapters/snapshot/leasemanager.go index 4022974632..3c121b8e27 100644 --- a/builder/builder-next/adapters/snapshot/leasemanager.go +++ b/builder/builder-next/adapters/snapshot/leasemanager.go @@ -4,7 +4,7 @@ import ( "context" "sync" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/leases" "github.com/containerd/log" bolt "go.etcd.io/bbolt" ) diff --git a/builder/builder-next/adapters/snapshot/snapshot.go b/builder/builder-next/adapters/snapshot/snapshot.go index cba0dea958..72dbbd3d30 100644 --- a/builder/builder-next/adapters/snapshot/snapshot.go +++ b/builder/builder-next/adapters/snapshot/snapshot.go @@ -7,9 +7,9 @@ import ( "strings" "sync" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/daemon/graphdriver" "github.com/docker/docker/layer" diff --git a/builder/builder-next/builder.go b/builder/builder-next/builder.go index cd66cd4a06..e147340acb 100644 --- a/builder/builder-next/builder.go +++ b/builder/builder-next/builder.go @@ -10,7 +10,7 @@ import ( "sync" "time" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/containerd/platforms" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/backend" diff --git a/builder/builder-next/controller.go b/builder/builder-next/controller.go index da37af2a80..3a3fdaecd6 100644 --- a/builder/builder-next/controller.go +++ b/builder/builder-next/controller.go @@ -8,10 +8,10 @@ import ( "runtime" "time" - ctd "github.com/containerd/containerd" - "github.com/containerd/containerd/content/local" - ctdmetadata "github.com/containerd/containerd/metadata" - "github.com/containerd/containerd/snapshots" + ctd "github.com/containerd/containerd/v2/client" + ctdmetadata "github.com/containerd/containerd/v2/core/metadata" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/containerd/log" "github.com/containerd/platforms" "github.com/docker/docker/api/types" diff --git a/builder/builder-next/exporter/mobyexporter/export.go b/builder/builder-next/exporter/mobyexporter/export.go index 7f705a75e9..e2b2f7f0d1 100644 --- a/builder/builder-next/exporter/mobyexporter/export.go +++ b/builder/builder-next/exporter/mobyexporter/export.go @@ -6,8 +6,8 @@ import ( "fmt" "strings" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/leases" "github.com/containerd/log" distref "github.com/distribution/reference" "github.com/docker/docker/image" diff --git a/builder/builder-next/worker/worker.go b/builder/builder-next/worker/worker.go index e8e7af650c..9d1f0ee4f7 100644 --- a/builder/builder-next/worker/worker.go +++ b/builder/builder-next/worker/worker.go @@ -7,10 +7,10 @@ import ( nethttp "net/http" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/gc" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/rootfs" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/gc" + "github.com/containerd/containerd/v2/pkg/rootfs" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/cmd/dockerd/daemon.go b/cmd/dockerd/daemon.go index e3a96864c4..53b4f104d2 100644 --- a/cmd/dockerd/daemon.go +++ b/cmd/dockerd/daemon.go @@ -14,8 +14,8 @@ import ( "sync" "time" - containerddefaults "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/tracing" + containerddefaults "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "github.com/docker/docker/api" apiserver "github.com/docker/docker/api/server" diff --git a/container/container.go b/container/container.go index 071e9f5a0b..c16a353fa8 100644 --- a/container/container.go +++ b/container/container.go @@ -13,7 +13,7 @@ import ( "syscall" "time" - "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/containerd/platforms" containertypes "github.com/docker/docker/api/types/container" diff --git a/container/exec.go b/container/exec.go index 328b596b04..e55bdcbab3 100644 --- a/container/exec.go +++ b/container/exec.go @@ -5,7 +5,7 @@ import ( "runtime" "sync" - "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/docker/docker/container/stream" "github.com/docker/docker/libcontainerd/types" diff --git a/container/stream/streams.go b/container/stream/streams.go index aa9b57a4a5..aa1c748557 100644 --- a/container/stream/streams.go +++ b/container/stream/streams.go @@ -7,7 +7,7 @@ import ( "io" "sync" - "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/docker/docker/container/stream/bytespipe" "github.com/docker/docker/pkg/pools" diff --git a/daemon/apparmor_default.go b/daemon/apparmor_default.go index 81e10b6cbe..5a3121d05b 100644 --- a/daemon/apparmor_default.go +++ b/daemon/apparmor_default.go @@ -5,7 +5,7 @@ package daemon // import "github.com/docker/docker/daemon" import ( "fmt" - "github.com/containerd/containerd/pkg/apparmor" + "github.com/containerd/containerd/v2/pkg/apparmor" aaprofile "github.com/docker/docker/profiles/apparmor" ) diff --git a/daemon/containerd/cache.go b/daemon/containerd/cache.go index 271760dd58..d99cee7145 100644 --- a/daemon/containerd/cache.go +++ b/daemon/containerd/cache.go @@ -6,7 +6,7 @@ import ( "errors" "fmt" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/docker/docker/api/types/backend" diff --git a/daemon/containerd/fake_service_test.go b/daemon/containerd/fake_service_test.go index f615021cb5..8b200d1c5a 100644 --- a/daemon/containerd/fake_service_test.go +++ b/daemon/containerd/fake_service_test.go @@ -10,11 +10,12 @@ import ( "testing" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/metadata" - "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/leases" + "github.com/containerd/containerd/v2/core/metadata" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/defaults" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/container" daemonevents "github.com/docker/docker/daemon/events" @@ -29,7 +30,7 @@ func fakeImageService(t testing.TB, ctx context.Context, cs content.Store) *Imag mdb := newTestDB(ctx, t) snapshotters := map[string]snapshots.Snapshotter{ - containerd.DefaultSnapshotter: snapshotter, + defaults.DefaultSnapshotter: snapshotter, } service := &ImageService{ @@ -38,7 +39,7 @@ func fakeImageService(t testing.TB, ctx context.Context, cs content.Store) *Imag content: cs, eventsService: daemonevents.New(), snapshotterServices: snapshotters, - snapshotter: containerd.DefaultSnapshotter, + snapshotter: defaults.DefaultSnapshotter, } // containerd.Image gets the services directly from containerd.Client diff --git a/daemon/containerd/handlers.go b/daemon/containerd/handlers.go index ad1b8d4b66..4349894f97 100644 --- a/daemon/containerd/handlers.go +++ b/daemon/containerd/handlers.go @@ -3,8 +3,8 @@ package containerd import ( "context" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/daemon/containerd/image.go b/daemon/containerd/image.go index 91dee744de..a3899665da 100644 --- a/daemon/containerd/image.go +++ b/daemon/containerd/image.go @@ -7,7 +7,7 @@ import ( "strconv" "strings" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_builder.go b/daemon/containerd/image_builder.go index a1b7a757b4..c70559f14f 100644 --- a/daemon/containerd/image_builder.go +++ b/daemon/containerd/image_builder.go @@ -11,12 +11,12 @@ import ( "runtime" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/rootfs" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/rootfs" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_changes.go b/daemon/containerd/image_changes.go index 69e09bf2f5..5c68402af0 100644 --- a/daemon/containerd/image_changes.go +++ b/daemon/containerd/image_changes.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/log" "github.com/docker/docker/container" "github.com/docker/docker/pkg/archive" diff --git a/daemon/containerd/image_children.go b/daemon/containerd/image_children.go index 2e4abc4373..74af3ec3e7 100644 --- a/daemon/containerd/image_children.go +++ b/daemon/containerd/image_children.go @@ -3,7 +3,7 @@ package containerd import ( "context" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" "github.com/docker/docker/errdefs" "github.com/docker/docker/image" "github.com/opencontainers/go-digest" diff --git a/daemon/containerd/image_commit.go b/daemon/containerd/image_commit.go index befba724c8..37c6da7928 100644 --- a/daemon/containerd/image_commit.go +++ b/daemon/containerd/image_commit.go @@ -10,10 +10,10 @@ import ( "strings" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/docker/docker/api/types/backend" diff --git a/daemon/containerd/image_delete.go b/daemon/containerd/image_delete.go index 5c4e93090a..28a66239c3 100644 --- a/daemon/containerd/image_delete.go +++ b/daemon/containerd/image_delete.go @@ -6,7 +6,7 @@ import ( "strings" "time" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/daemon/containerd/image_delete_test.go b/daemon/containerd/image_delete_test.go index 615ffa8b59..7b830facb4 100644 --- a/daemon/containerd/image_delete_test.go +++ b/daemon/containerd/image_delete_test.go @@ -4,9 +4,9 @@ import ( "context" "testing" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/metadata" - "github.com/containerd/containerd/namespaces" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/metadata" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log/logtest" "github.com/docker/docker/container" daemonevents "github.com/docker/docker/daemon/events" diff --git a/daemon/containerd/image_events.go b/daemon/containerd/image_events.go index b07c11807d..6dbcecd0f2 100644 --- a/daemon/containerd/image_events.go +++ b/daemon/containerd/image_events.go @@ -3,7 +3,7 @@ package containerd import ( "context" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" "github.com/docker/docker/api/types/backend" "github.com/docker/docker/api/types/events" ) diff --git a/daemon/containerd/image_exporter.go b/daemon/containerd/image_exporter.go index c2a5ed5a41..6b69cce93c 100644 --- a/daemon/containerd/image_exporter.go +++ b/daemon/containerd/image_exporter.go @@ -6,11 +6,11 @@ import ( "io" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/archive" - "github.com/containerd/containerd/leases" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/archive" + "github.com/containerd/containerd/v2/core/leases" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_history.go b/daemon/containerd/image_history.go index bc91762c3e..32afe7d640 100644 --- a/daemon/containerd/image_history.go +++ b/daemon/containerd/image_history.go @@ -4,7 +4,7 @@ import ( "context" "time" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" "github.com/containerd/log" "github.com/containerd/platforms" "github.com/distribution/reference" diff --git a/daemon/containerd/image_import.go b/daemon/containerd/image_import.go index 3f20ae90b1..c78bafa7bc 100644 --- a/daemon/containerd/image_import.go +++ b/daemon/containerd/image_import.go @@ -9,8 +9,8 @@ import ( "io" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_inspect.go b/daemon/containerd/image_inspect.go index 6f4c3dfdff..b5fb8c8aeb 100644 --- a/daemon/containerd/image_inspect.go +++ b/daemon/containerd/image_inspect.go @@ -8,7 +8,7 @@ import ( "sync/atomic" "time" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_list.go b/daemon/containerd/image_list.go index bd386585b2..670f9f7eaf 100644 --- a/daemon/containerd/image_list.go +++ b/daemon/containerd/image_list.go @@ -9,10 +9,10 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_list_test.go b/daemon/containerd/image_list_test.go index 3d07511b3d..0242536ad5 100644 --- a/daemon/containerd/image_list_test.go +++ b/daemon/containerd/image_list_test.go @@ -10,9 +10,9 @@ import ( "testing" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log/logtest" "github.com/containerd/platforms" imagetypes "github.com/docker/docker/api/types/image" diff --git a/daemon/containerd/image_load_test.go b/daemon/containerd/image_load_test.go index f68b2c680a..4b4629dece 100644 --- a/daemon/containerd/image_load_test.go +++ b/daemon/containerd/image_load_test.go @@ -8,9 +8,9 @@ import ( "path/filepath" "testing" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/containerd/platforms" "github.com/docker/docker/errdefs" "github.com/docker/docker/internal/testutils/specialimage" diff --git a/daemon/containerd/image_manifest.go b/daemon/containerd/image_manifest.go index f14c7cf892..f6f95e3601 100644 --- a/daemon/containerd/image_manifest.go +++ b/daemon/containerd/image_manifest.go @@ -4,9 +4,9 @@ import ( "context" "encoding/json" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/platforms" "github.com/docker/docker/errdefs" diff --git a/daemon/containerd/image_prune.go b/daemon/containerd/image_prune.go index f67e9a2941..bf61138b57 100644 --- a/daemon/containerd/image_prune.go +++ b/daemon/containerd/image_prune.go @@ -5,9 +5,9 @@ import ( "sort" "strings" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/tracing" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/tracing" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/daemon/containerd/image_pull.go b/daemon/containerd/image_pull.go index 376f76d3df..48644808ff 100644 --- a/daemon/containerd/image_pull.go +++ b/daemon/containerd/image_pull.go @@ -8,10 +8,10 @@ import ( "strings" "time" - "github.com/containerd/containerd" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/pkg/snapshotters" - "github.com/containerd/containerd/remotes/docker" + containerd "github.com/containerd/containerd/v2/client" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/pkg/snapshotters" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_push.go b/daemon/containerd/image_push.go index 674777673a..5eb549e688 100644 --- a/daemon/containerd/image_push.go +++ b/daemon/containerd/image_push.go @@ -8,11 +8,11 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - containerdlabels "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + containerdlabels "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/containerd/image_push_test.go b/daemon/containerd/image_push_test.go index 41d3488e9d..df9f39f187 100644 --- a/daemon/containerd/image_push_test.go +++ b/daemon/containerd/image_push_test.go @@ -10,8 +10,8 @@ import ( "slices" "testing" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/namespaces" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/platforms" "github.com/docker/docker/errdefs" "github.com/docker/docker/internal/testutils/specialimage" diff --git a/daemon/containerd/image_save_test.go b/daemon/containerd/image_save_test.go index 13a9c86565..7fece39a2b 100644 --- a/daemon/containerd/image_save_test.go +++ b/daemon/containerd/image_save_test.go @@ -6,7 +6,7 @@ import ( "path/filepath" "testing" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/platforms" "github.com/docker/docker/errdefs" "github.com/docker/docker/internal/testutils/specialimage" diff --git a/daemon/containerd/image_snapshot.go b/daemon/containerd/image_snapshot.go index 8c179be51b..78362e6d3c 100644 --- a/daemon/containerd/image_snapshot.go +++ b/daemon/containerd/image_snapshot.go @@ -4,10 +4,10 @@ import ( "context" "fmt" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/docker/docker/container" diff --git a/daemon/containerd/image_snapshot_unix.go b/daemon/containerd/image_snapshot_unix.go index 1951281560..74985f1d1c 100644 --- a/daemon/containerd/image_snapshot_unix.go +++ b/daemon/containerd/image_snapshot_unix.go @@ -9,8 +9,8 @@ import ( "path/filepath" "syscall" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/continuity/fs" "github.com/containerd/continuity/sysx" "github.com/docker/docker/pkg/idtools" diff --git a/daemon/containerd/image_snapshot_windows.go b/daemon/containerd/image_snapshot_windows.go index 12aeb5be2a..2bbbdbbb81 100644 --- a/daemon/containerd/image_snapshot_windows.go +++ b/daemon/containerd/image_snapshot_windows.go @@ -3,8 +3,8 @@ package containerd import ( "context" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" ) const remapSuffix = "-remap" diff --git a/daemon/containerd/image_tag.go b/daemon/containerd/image_tag.go index 7219e0941d..1b32dbdedc 100644 --- a/daemon/containerd/image_tag.go +++ b/daemon/containerd/image_tag.go @@ -4,7 +4,7 @@ import ( "context" "fmt" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/daemon/containerd/image_test.go b/daemon/containerd/image_test.go index 9cbfb85b2d..8375fcb248 100644 --- a/daemon/containerd/image_test.go +++ b/daemon/containerd/image_test.go @@ -7,10 +7,10 @@ import ( "path/filepath" "testing" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/metadata" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/snapshots" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/metadata" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log/logtest" "github.com/distribution/reference" dockerimages "github.com/docker/docker/daemon/images" diff --git a/daemon/containerd/leases.go b/daemon/containerd/leases.go index e2a38e5b57..a73e20e8bc 100644 --- a/daemon/containerd/leases.go +++ b/daemon/containerd/leases.go @@ -4,7 +4,7 @@ import ( "context" "time" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/leases" "github.com/containerd/log" ) diff --git a/daemon/containerd/progress.go b/daemon/containerd/progress.go index 9b18604b78..d14e12f822 100644 --- a/daemon/containerd/progress.go +++ b/daemon/containerd/progress.go @@ -8,12 +8,12 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/pkg/snapshotters" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + c8dimages "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/core/snapshots" + "github.com/containerd/containerd/v2/pkg/snapshotters" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/daemon/containerd/resolver.go b/daemon/containerd/resolver.go index 34c25e3005..f7b218dde1 100644 --- a/daemon/containerd/resolver.go +++ b/daemon/containerd/resolver.go @@ -4,9 +4,9 @@ import ( "context" "net/http" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/version" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/version" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/daemon/containerd/service.go b/daemon/containerd/service.go index 584b3ef5a6..e2298bbf69 100644 --- a/daemon/containerd/service.go +++ b/daemon/containerd/service.go @@ -5,12 +5,12 @@ import ( "fmt" "sync/atomic" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/snapshots" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/plugins" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" @@ -112,7 +112,7 @@ func (i *ImageService) CountImages(ctx context.Context) int { func (i *ImageService) LayerStoreStatus() [][2]string { // TODO(thaJeztah) do we want to add more details about the driver here? return [][2]string{ - {"driver-type", string(plugin.SnapshotPlugin)}, + {"driver-type", string(plugins.SnapshotPlugin)}, } } diff --git a/daemon/containerd/soft_delete.go b/daemon/containerd/soft_delete.go index afa5179fd7..2644294104 100644 --- a/daemon/containerd/soft_delete.go +++ b/daemon/containerd/soft_delete.go @@ -3,7 +3,7 @@ package containerd import ( "context" - c8dimages "github.com/containerd/containerd/images" + c8dimages "github.com/containerd/containerd/v2/core/images" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/errdefs" "github.com/opencontainers/go-digest" diff --git a/daemon/containerd/store.go b/daemon/containerd/store.go index 1f7d4583ed..19148cd3c5 100644 --- a/daemon/containerd/store.go +++ b/daemon/containerd/store.go @@ -3,8 +3,8 @@ package containerd import ( "context" - "github.com/containerd/containerd/content" - containerdlabels "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + containerdlabels "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/distribution/reference" "github.com/opencontainers/go-digest" diff --git a/daemon/content.go b/daemon/content.go index 9338851da9..fe8b28b24a 100644 --- a/daemon/content.go +++ b/daemon/content.go @@ -5,11 +5,11 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/metadata" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/metadata" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/daemon/daemon.go b/daemon/daemon.go index 21bd07e0a2..e938773682 100644 --- a/daemon/daemon.go +++ b/daemon/daemon.go @@ -24,9 +24,9 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/pkg/dialer" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/containerd/v2/pkg/dialer" "github.com/containerd/log" "github.com/distribution/reference" dist "github.com/docker/distribution" @@ -1069,7 +1069,7 @@ func NewDaemon(ctx context.Context, config *config.Config, pluginStore *plugin.S // FIXME(thaJeztah): implement automatic snapshotter-selection similar to graph-driver selection; see https://github.com/moby/moby/issues/44076 if driverName == "" { - driverName = containerd.DefaultSnapshotter + driverName = defaults.DefaultSnapshotter } // Configure and validate the kernels security support. Note this is a Linux/FreeBSD diff --git a/daemon/exec.go b/daemon/exec.go index 4f37756c88..04fa5184cb 100644 --- a/daemon/exec.go +++ b/daemon/exec.go @@ -9,7 +9,7 @@ import ( "strings" "time" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/docker/docker/api/types/backend" containertypes "github.com/docker/docker/api/types/container" diff --git a/daemon/exec_linux.go b/daemon/exec_linux.go index 3ab7492b22..6afaf9972a 100644 --- a/daemon/exec_linux.go +++ b/daemon/exec_linux.go @@ -3,9 +3,9 @@ package daemon // import "github.com/docker/docker/daemon" import ( "context" - "github.com/containerd/containerd" - coci "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/apparmor" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/apparmor" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/docker/docker/container" "github.com/docker/docker/daemon/config" "github.com/docker/docker/oci/caps" diff --git a/daemon/exec_linux_test.go b/daemon/exec_linux_test.go index b3d7ddd154..a5c7b3affd 100644 --- a/daemon/exec_linux_test.go +++ b/daemon/exec_linux_test.go @@ -6,7 +6,7 @@ import ( "context" "testing" - "github.com/containerd/containerd/pkg/apparmor" + "github.com/containerd/containerd/v2/pkg/apparmor" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" specs "github.com/opencontainers/runtime-spec/specs-go" diff --git a/daemon/graphdriver/overlay2/check.go b/daemon/graphdriver/overlay2/check.go index d4b5994c99..757d1124d2 100644 --- a/daemon/graphdriver/overlay2/check.go +++ b/daemon/graphdriver/overlay2/check.go @@ -9,7 +9,7 @@ import ( "path/filepath" "syscall" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/docker/docker/daemon/graphdriver/overlayutils" "github.com/docker/docker/pkg/system" "github.com/moby/sys/userns" diff --git a/daemon/graphdriver/overlayutils/userxattr.go b/daemon/graphdriver/overlayutils/userxattr.go index f45923d266..9c6a8d9ab8 100644 --- a/daemon/graphdriver/overlayutils/userxattr.go +++ b/daemon/graphdriver/overlayutils/userxattr.go @@ -25,7 +25,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/log" "github.com/docker/docker/pkg/parsers/kernel" "github.com/moby/sys/userns" diff --git a/daemon/hosts.go b/daemon/hosts.go index 46df548af7..0c4f84bc23 100644 --- a/daemon/hosts.go +++ b/daemon/hosts.go @@ -13,8 +13,8 @@ import ( "runtime" "strings" - "github.com/containerd/containerd/remotes/docker" - hostconfig "github.com/containerd/containerd/remotes/docker/config" + "github.com/containerd/containerd/v2/core/remotes/docker" + hostconfig "github.com/containerd/containerd/v2/core/remotes/docker/config" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/registry" "github.com/pkg/errors" diff --git a/daemon/hosts_test.go b/daemon/hosts_test.go index 98d962e266..282492fb29 100644 --- a/daemon/hosts_test.go +++ b/daemon/hosts_test.go @@ -3,7 +3,7 @@ package daemon // import "github.com/docker/docker/daemon" import ( "testing" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker" "gotest.tools/v3/assert" is "gotest.tools/v3/assert/cmp" ) diff --git a/daemon/images/image.go b/daemon/images/image.go index cbd69d8517..8faa161a2b 100644 --- a/daemon/images/image.go +++ b/daemon/images/image.go @@ -6,9 +6,9 @@ import ( "fmt" "io" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" diff --git a/daemon/images/image_pull.go b/daemon/images/image_pull.go index af9f7a0be8..b9e41aaa83 100644 --- a/daemon/images/image_pull.go +++ b/daemon/images/image_pull.go @@ -5,8 +5,8 @@ import ( "io" "time" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/log" "github.com/distribution/reference" "github.com/docker/docker/api/types/backend" diff --git a/daemon/images/service.go b/daemon/images/service.go index 4af7ab4a91..213eec28bd 100644 --- a/daemon/images/service.go +++ b/daemon/images/service.go @@ -6,8 +6,8 @@ import ( "os" "sync/atomic" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/leases" "github.com/docker/docker/container" daemonevents "github.com/docker/docker/daemon/events" "github.com/docker/docker/distribution" diff --git a/daemon/images/store.go b/daemon/images/store.go index 98a16240a4..81925d0bef 100644 --- a/daemon/images/store.go +++ b/daemon/images/store.go @@ -4,9 +4,9 @@ import ( "context" "sync" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/namespaces" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/docker/docker/distribution" diff --git a/daemon/images/store_test.go b/daemon/images/store_test.go index 876bb21bfd..322b7bd0d0 100644 --- a/daemon/images/store_test.go +++ b/daemon/images/store_test.go @@ -6,11 +6,11 @@ import ( "path/filepath" "testing" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/metadata" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/metadata" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/plugins/content/local" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/image" "github.com/opencontainers/go-digest" diff --git a/daemon/info.go b/daemon/info.go index 3d46eedc3f..339d9664ef 100644 --- a/daemon/info.go +++ b/daemon/info.go @@ -12,7 +12,7 @@ import ( "strings" "time" - "github.com/containerd/containerd/tracing" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "github.com/docker/docker/api" "github.com/docker/docker/api/types" diff --git a/daemon/internal/filedescriptors/filiedescriptors_linux.go b/daemon/internal/filedescriptors/filiedescriptors_linux.go index c3848ad1ba..ce0e99bbcc 100644 --- a/daemon/internal/filedescriptors/filiedescriptors_linux.go +++ b/daemon/internal/filedescriptors/filiedescriptors_linux.go @@ -6,7 +6,7 @@ import ( "io" "os" - "github.com/containerd/containerd/tracing" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "golang.org/x/sys/unix" ) diff --git a/daemon/logger/loggerutils/logfile.go b/daemon/logger/loggerutils/logfile.go index e9583521f6..ce52bca13f 100644 --- a/daemon/logger/loggerutils/logfile.go +++ b/daemon/logger/loggerutils/logfile.go @@ -17,13 +17,12 @@ import ( "sync" "time" - "github.com/containerd/containerd/tracing" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "github.com/docker/docker/daemon/logger" "github.com/docker/docker/pkg/pools" "github.com/pkg/errors" "go.opentelemetry.io/otel/attribute" - "go.opentelemetry.io/otel/trace" ) // rotateFileMetadata is a metadata of the gzip header of the compressed log file @@ -731,7 +730,7 @@ func getTailFiles(ctx context.Context, files []fileOpener, nLines int, getTailRe if nLines <= 0 { for _, fo := range files { - span.AddEvent("Open file", trace.WithAttributes(attribute.String("file", fo.Ref()))) + span.AddEvent("Open file", attribute.String("file", fo.Ref())) ra, err := fo.ReaderAt(ctx) if err != nil { @@ -751,14 +750,14 @@ func getTailFiles(ctx context.Context, files []fileOpener, nLines int, getTailRe fo := files[i] fileAttr := attribute.String("file", fo.Ref()) - span.AddEvent("Open file", trace.WithAttributes(fileAttr)) + span.AddEvent("Open file", fileAttr) ra, err := fo.ReaderAt(ctx) if err != nil { return nil, err } - span.AddEvent("Scan file to tail", trace.WithAttributes(fileAttr, attribute.Int("remaining_lines", nLines))) + span.AddEvent("Scan file to tail", fileAttr, attribute.Int("remaining_lines", nLines)) tail, n, err := getTailReader(ctx, ra, nLines) if err != nil { diff --git a/daemon/logs.go b/daemon/logs.go index 1c72eee410..1b79aaca03 100644 --- a/daemon/logs.go +++ b/daemon/logs.go @@ -5,7 +5,7 @@ import ( "strconv" "time" - "github.com/containerd/containerd/tracing" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "github.com/docker/docker/api/types/backend" containertypes "github.com/docker/docker/api/types/container" diff --git a/daemon/migration.go b/daemon/migration.go index 592554b6be..4610fd9d07 100644 --- a/daemon/migration.go +++ b/daemon/migration.go @@ -4,7 +4,7 @@ import ( "context" "encoding/json" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/log" "github.com/containerd/platforms" "github.com/docker/docker/api/types/backend" diff --git a/daemon/nvidia_linux.go b/daemon/nvidia_linux.go index 60d3165a59..abc6b4a351 100644 --- a/daemon/nvidia_linux.go +++ b/daemon/nvidia_linux.go @@ -6,7 +6,7 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/contrib/nvidia" + "github.com/containerd/containerd/v2/contrib/nvidia" "github.com/docker/docker/daemon/internal/capabilities" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" diff --git a/daemon/oci_linux.go b/daemon/oci_linux.go index 67431ab3a8..12e4d6c29d 100644 --- a/daemon/oci_linux.go +++ b/daemon/oci_linux.go @@ -9,9 +9,9 @@ import ( "strings" cdcgroups "github.com/containerd/cgroups/v3" - "github.com/containerd/containerd/containers" - coci "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/apparmor" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/apparmor" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" diff --git a/daemon/oci_opts.go b/daemon/oci_opts.go index 3816bce19f..43c208bca3 100644 --- a/daemon/oci_opts.go +++ b/daemon/oci_opts.go @@ -3,8 +3,8 @@ package daemon import ( "context" - "github.com/containerd/containerd/containers" - coci "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/docker/docker/container" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/daemon/oci_windows.go b/daemon/oci_windows.go index e1801d2aa1..df1de26305 100644 --- a/daemon/oci_windows.go +++ b/daemon/oci_windows.go @@ -10,7 +10,7 @@ import ( "strings" "github.com/Microsoft/hcsshim" - coci "github.com/containerd/containerd/oci" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/docker/docker/api/types/backend" containertypes "github.com/docker/docker/api/types/container" diff --git a/daemon/runtime_unix.go b/daemon/runtime_unix.go index 71bbac969d..d0abc99d6c 100644 --- a/daemon/runtime_unix.go +++ b/daemon/runtime_unix.go @@ -16,7 +16,7 @@ import ( "strings" runcoptions "github.com/containerd/containerd/api/types/runc/options" - "github.com/containerd/containerd/plugin" + "github.com/containerd/containerd/v2/plugins" "github.com/containerd/log" "github.com/docker/docker/daemon/config" "github.com/docker/docker/errdefs" @@ -56,7 +56,7 @@ func stockRuntimes() map[string]string { func defaultV2ShimConfig(conf *config.Config, runtimePath string) *shimConfig { shim := &shimConfig{ - Shim: plugin.RuntimeRuncV2, + Shim: plugins.RuntimeRuncV2, Opts: &runcoptions.Options{ BinaryName: runtimePath, Root: filepath.Join(conf.ExecRoot, "runtime-"+defaultRuntimeName), diff --git a/daemon/runtime_unix_test.go b/daemon/runtime_unix_test.go index c73db049a6..0dd6ec447b 100644 --- a/daemon/runtime_unix_test.go +++ b/daemon/runtime_unix_test.go @@ -10,8 +10,8 @@ import ( "dario.cat/mergo" runcoptions "github.com/containerd/containerd/api/types/runc/options" - runtimeoptions "github.com/containerd/containerd/pkg/runtimeoptions/v1" - "github.com/containerd/containerd/plugin" + runtimeoptions "github.com/containerd/containerd/api/types/runtimeoptions/v1" + "github.com/containerd/containerd/v2/plugins" "github.com/docker/docker/api/types/system" "github.com/docker/docker/daemon/config" "github.com/docker/docker/errdefs" @@ -202,7 +202,7 @@ func TestGetRuntime(t *testing.T) { const shimWithOptsName = "shimwithopts" shimWithOpts := system.Runtime{ - Type: plugin.RuntimeRuncV2, + Type: plugins.RuntimeRuncV2, Options: map[string]interface{}{"IoUid": 42}, } @@ -350,7 +350,7 @@ func TestGetRuntime(t *testing.T) { assert.Check(t, err) assert.Check(t, is.Equal(shim, stockRuntime.Shim)) runcopts, ok := opts.(*runcoptions.Options) - if assert.Check(t, ok, "runtimes.Get() opts = type %T, want *v2runcoptions.Options", opts) { + if assert.Check(t, ok, "runtimes.Get() opts = type %T, want *runcoptions.Options", opts) { wrapper, err := os.ReadFile(runcopts.BinaryName) if assert.Check(t, err) { assert.Check(t, is.Contains(string(wrapper), diff --git a/daemon/seccomp_linux.go b/daemon/seccomp_linux.go index 3dbd35e3a3..1602edd609 100644 --- a/daemon/seccomp_linux.go +++ b/daemon/seccomp_linux.go @@ -4,8 +4,8 @@ import ( "context" "fmt" - "github.com/containerd/containerd/containers" - coci "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/log" "github.com/docker/docker/container" dconfig "github.com/docker/docker/daemon/config" diff --git a/daemon/seccomp_linux_test.go b/daemon/seccomp_linux_test.go index 7c623277a7..dd1a9a5f81 100644 --- a/daemon/seccomp_linux_test.go +++ b/daemon/seccomp_linux_test.go @@ -3,7 +3,7 @@ package daemon // import "github.com/docker/docker/daemon" import ( "testing" - coci "github.com/containerd/containerd/oci" + coci "github.com/containerd/containerd/v2/pkg/oci" containertypes "github.com/docker/docker/api/types/container" "github.com/docker/docker/container" dconfig "github.com/docker/docker/daemon/config" diff --git a/daemon/seccomp_unsupported.go b/daemon/seccomp_unsupported.go index 0fa73bd647..e1bc3d1a46 100644 --- a/daemon/seccomp_unsupported.go +++ b/daemon/seccomp_unsupported.go @@ -5,8 +5,8 @@ package daemon // import "github.com/docker/docker/daemon" import ( "context" - "github.com/containerd/containerd/containers" - coci "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/docker/docker/container" ) diff --git a/daemon/snapshotter/mount.go b/daemon/snapshotter/mount.go index 1f94901c92..8806d17d8e 100644 --- a/daemon/snapshotter/mount.go +++ b/daemon/snapshotter/mount.go @@ -5,7 +5,7 @@ import ( "os" "path/filepath" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/log" "github.com/docker/docker/daemon/internal/mountref" "github.com/docker/docker/pkg/idtools" diff --git a/daemon/snapshotter/mount_unix.go b/daemon/snapshotter/mount_unix.go index ccb8073509..fe21e8119b 100644 --- a/daemon/snapshotter/mount_unix.go +++ b/daemon/snapshotter/mount_unix.go @@ -3,7 +3,7 @@ package snapshotter import ( - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/moby/sys/mountinfo" "golang.org/x/sys/unix" ) diff --git a/daemon/snapshotter/mount_windows.go b/daemon/snapshotter/mount_windows.go index de82e1c609..30a595c9bd 100644 --- a/daemon/snapshotter/mount_windows.go +++ b/daemon/snapshotter/mount_windows.go @@ -1,6 +1,6 @@ package snapshotter -import "github.com/containerd/containerd/mount" +import "github.com/containerd/containerd/v2/core/mount" func isMounted(string) bool { return false } diff --git a/daemon/start.go b/daemon/start.go index 3c3307e935..a49118bb03 100644 --- a/daemon/start.go +++ b/daemon/start.go @@ -4,8 +4,8 @@ import ( "context" "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/docker/docker/api/types/backend" "github.com/docker/docker/api/types/events" diff --git a/distribution/manifest.go b/distribution/manifest.go index ca99ce6d0f..ce482f67c7 100644 --- a/distribution/manifest.go +++ b/distribution/manifest.go @@ -8,8 +8,8 @@ import ( "os" "strings" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/distribution/manifest_test.go b/distribution/manifest_test.go index 2daafbe7d2..c6d29f3e92 100644 --- a/distribution/manifest_test.go +++ b/distribution/manifest_test.go @@ -8,9 +8,9 @@ import ( "sync" "testing" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/plugins/content/local" cerrdefs "github.com/containerd/errdefs" "github.com/distribution/reference" "github.com/docker/distribution" diff --git a/image/tarexport/load.go b/image/tarexport/load.go index 2bbdde0226..25b68aee36 100644 --- a/image/tarexport/load.go +++ b/image/tarexport/load.go @@ -11,7 +11,7 @@ import ( "reflect" "runtime" - "github.com/containerd/containerd/tracing" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "github.com/distribution/reference" "github.com/docker/distribution" diff --git a/image/tarexport/save.go b/image/tarexport/save.go index 76b73ddade..3f25a49faf 100644 --- a/image/tarexport/save.go +++ b/image/tarexport/save.go @@ -10,8 +10,8 @@ import ( "path/filepath" "time" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/tracing" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/tracing" "github.com/containerd/log" "github.com/containerd/platforms" "github.com/distribution/reference" diff --git a/integration-cli/requirements_test.go b/integration-cli/requirements_test.go index 66f482fc94..4c1a475a91 100644 --- a/integration-cli/requirements_test.go +++ b/integration-cli/requirements_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/containerd/containerd/plugin" + "github.com/containerd/containerd/v2/plugins" "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/swarm" "github.com/docker/docker/client" @@ -88,7 +88,7 @@ func Apparmor() bool { func containerdSnapshotterEnabled() bool { for _, v := range testEnv.DaemonInfo.DriverStatus { if v[0] == "driver-type" { - return v[1] == string(plugin.SnapshotPlugin) + return v[1] == string(plugins.SnapshotPlugin) } } return false diff --git a/integration/container/create_test.go b/integration/container/create_test.go index d576963874..e2cdc65a73 100644 --- a/integration/container/create_test.go +++ b/integration/container/create_test.go @@ -10,7 +10,7 @@ import ( "testing" "time" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/docker/docker/api/types/container" "github.com/docker/docker/api/types/network" "github.com/docker/docker/api/types/versions" diff --git a/integration/image/pull_test.go b/integration/image/pull_test.go index 6931bbd42c..05b17f489d 100644 --- a/integration/image/pull_test.go +++ b/integration/image/pull_test.go @@ -11,10 +11,10 @@ import ( "strings" "testing" - "github.com/containerd/containerd" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" - c8dimages "github.com/containerd/containerd/images" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/containerd/platforms" "github.com/docker/docker/api/types/image" "github.com/docker/docker/errdefs" diff --git a/integration/plugin/common/plugin_test.go b/integration/plugin/common/plugin_test.go index b24486ba66..6f425f7277 100644 --- a/integration/plugin/common/plugin_test.go +++ b/integration/plugin/common/plugin_test.go @@ -13,8 +13,8 @@ import ( "strings" "testing" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes/docker" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/docker/docker/api/types" registrytypes "github.com/docker/docker/api/types/registry" "github.com/docker/docker/api/types/system" diff --git a/libcontainerd/libcontainerd_linux.go b/libcontainerd/libcontainerd_linux.go index ec195a7905..17b62971be 100644 --- a/libcontainerd/libcontainerd_linux.go +++ b/libcontainerd/libcontainerd_linux.go @@ -3,7 +3,7 @@ package libcontainerd // import "github.com/docker/docker/libcontainerd" import ( "context" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/docker/docker/libcontainerd/remote" libcontainerdtypes "github.com/docker/docker/libcontainerd/types" ) diff --git a/libcontainerd/libcontainerd_windows.go b/libcontainerd/libcontainerd_windows.go index 61f19ba087..7f87e439e4 100644 --- a/libcontainerd/libcontainerd_windows.go +++ b/libcontainerd/libcontainerd_windows.go @@ -3,7 +3,7 @@ package libcontainerd // import "github.com/docker/docker/libcontainerd" import ( "context" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/docker/docker/libcontainerd/local" "github.com/docker/docker/libcontainerd/remote" libcontainerdtypes "github.com/docker/docker/libcontainerd/types" diff --git a/libcontainerd/local/local_windows.go b/libcontainerd/local/local_windows.go index 20d9095389..3816a61cc0 100644 --- a/libcontainerd/local/local_windows.go +++ b/libcontainerd/local/local_windows.go @@ -17,8 +17,8 @@ import ( "time" "github.com/Microsoft/hcsshim" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/pkg/cio" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/docker/docker/errdefs" diff --git a/libcontainerd/remote/client.go b/libcontainerd/remote/client.go index c77c8cc024..a2dffef2af 100644 --- a/libcontainerd/remote/client.go +++ b/libcontainerd/remote/client.go @@ -13,15 +13,15 @@ import ( "syscall" "time" - "github.com/containerd/containerd" apievents "github.com/containerd/containerd/api/events" "github.com/containerd/containerd/api/types" runcoptions "github.com/containerd/containerd/api/types/runc/options" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/protobuf" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/archive" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/protobuf" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/typeurl/v2" diff --git a/libcontainerd/remote/client_io_windows.go b/libcontainerd/remote/client_io_windows.go index bbc51a4fc8..fbf71af814 100644 --- a/libcontainerd/remote/client_io_windows.go +++ b/libcontainerd/remote/client_io_windows.go @@ -6,7 +6,7 @@ import ( "sync" winio "github.com/Microsoft/go-winio" - "github.com/containerd/containerd/cio" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" "github.com/pkg/errors" ) diff --git a/libcontainerd/remote/client_linux.go b/libcontainerd/remote/client_linux.go index a629ab0e32..62cb782110 100644 --- a/libcontainerd/remote/client_linux.go +++ b/libcontainerd/remote/client_linux.go @@ -7,9 +7,9 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/containers" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" libcontainerdtypes "github.com/docker/docker/libcontainerd/types" "github.com/docker/docker/pkg/idtools" diff --git a/libcontainerd/remote/client_windows.go b/libcontainerd/remote/client_windows.go index be5566c0c7..917419e11f 100644 --- a/libcontainerd/remote/client_windows.go +++ b/libcontainerd/remote/client_windows.go @@ -7,9 +7,9 @@ import ( "path/filepath" "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/containers" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/containerd/log" libcontainerdtypes "github.com/docker/docker/libcontainerd/types" "github.com/opencontainers/runtime-spec/specs-go" diff --git a/libcontainerd/replace.go b/libcontainerd/replace.go index 29213f7f48..56a6f96cf6 100644 --- a/libcontainerd/replace.go +++ b/libcontainerd/replace.go @@ -3,7 +3,7 @@ package libcontainerd // import "github.com/docker/docker/libcontainerd" import ( "context" - "github.com/containerd/containerd" + containerd "github.com/containerd/containerd/v2/client" "github.com/containerd/log" "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" diff --git a/libcontainerd/shimopts/convert.go b/libcontainerd/shimopts/convert.go index 4da2fa9753..71a40ce54d 100644 --- a/libcontainerd/shimopts/convert.go +++ b/libcontainerd/shimopts/convert.go @@ -3,8 +3,8 @@ package shimopts import ( runhcsoptions "github.com/Microsoft/hcsshim/cmd/containerd-shim-runhcs-v1/options" runcoptions "github.com/containerd/containerd/api/types/runc/options" - runtimeoptions "github.com/containerd/containerd/pkg/runtimeoptions/v1" - "github.com/containerd/containerd/plugin" + runtimeoptions "github.com/containerd/containerd/api/types/runtimeoptions/v1" + "github.com/containerd/containerd/v2/plugins" "github.com/pelletier/go-toml" ) @@ -17,7 +17,7 @@ func Generate(runtimeType string, opts map[string]interface{}) (interface{}, err // options in the same way. var out interface{} switch runtimeType { - case plugin.RuntimeRuncV1, plugin.RuntimeRuncV2: + case plugins.RuntimeRuncV2: out = &runcoptions.Options{} case "io.containerd.runhcs.v1": out = &runhcsoptions.Options{} diff --git a/libcontainerd/supervisor/remote_daemon.go b/libcontainerd/supervisor/remote_daemon.go index 7611291971..9f30aca2ed 100644 --- a/libcontainerd/supervisor/remote_daemon.go +++ b/libcontainerd/supervisor/remote_daemon.go @@ -9,10 +9,10 @@ import ( "strings" "time" - "github.com/containerd/containerd" - "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/pkg/dialer" - "github.com/containerd/containerd/services/server/config" + containerd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/cmd/containerd/server/config" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/containerd/v2/pkg/dialer" "github.com/containerd/log" "github.com/docker/docker/pkg/pidfile" "github.com/docker/docker/pkg/process" diff --git a/libcontainerd/types/types.go b/libcontainerd/types/types.go index 38e1d9207a..5984baca9b 100644 --- a/libcontainerd/types/types.go +++ b/libcontainerd/types/types.go @@ -5,8 +5,8 @@ import ( "syscall" "time" - "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/opencontainers/runtime-spec/specs-go" ) diff --git a/oci/caps/utils_linux.go b/oci/caps/utils_linux.go index ffb301cf81..424cd6ea8b 100644 --- a/oci/caps/utils_linux.go +++ b/oci/caps/utils_linux.go @@ -3,7 +3,7 @@ import ( "context" "sync" - ccaps "github.com/containerd/containerd/pkg/cap" + ccaps "github.com/containerd/containerd/v2/pkg/cap" "github.com/containerd/log" ) diff --git a/oci/devices_linux.go b/oci/devices_linux.go index fe268dd270..d559a7c2e2 100644 --- a/oci/devices_linux.go +++ b/oci/devices_linux.go @@ -6,7 +6,7 @@ import ( "path/filepath" "strings" - coci "github.com/containerd/containerd/oci" + coci "github.com/containerd/containerd/v2/pkg/oci" "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/pkg/sysinfo/sysinfo_linux.go b/pkg/sysinfo/sysinfo_linux.go index b8a22682b7..ca2f30f1d7 100644 --- a/pkg/sysinfo/sysinfo_linux.go +++ b/pkg/sysinfo/sysinfo_linux.go @@ -11,7 +11,7 @@ import ( "github.com/containerd/cgroups/v3" "github.com/containerd/cgroups/v3/cgroup1" - "github.com/containerd/containerd/pkg/seccomp" + "github.com/containerd/containerd/v2/pkg/seccomp" "github.com/containerd/log" "github.com/moby/sys/mountinfo" ) diff --git a/pkg/sysinfo/sysinfo_linux_test.go b/pkg/sysinfo/sysinfo_linux_test.go index c88f1b0f5d..8138fe25fc 100644 --- a/pkg/sysinfo/sysinfo_linux_test.go +++ b/pkg/sysinfo/sysinfo_linux_test.go @@ -6,7 +6,7 @@ import ( "reflect" "testing" - "github.com/containerd/containerd/pkg/seccomp" + "github.com/containerd/containerd/v2/pkg/seccomp" ) func TestReadProcBool(t *testing.T) { diff --git a/plugin/backend_linux.go b/plugin/backend_linux.go index a77844ec98..aa5b28e6a6 100644 --- a/plugin/backend_linux.go +++ b/plugin/backend_linux.go @@ -14,10 +14,10 @@ import ( "strings" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/content" + c8dimages "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/log" "github.com/containerd/platforms" "github.com/distribution/reference" diff --git a/plugin/executor/containerd/containerd.go b/plugin/executor/containerd/containerd.go index b2974e708c..879f64713e 100644 --- a/plugin/executor/containerd/containerd.go +++ b/plugin/executor/containerd/containerd.go @@ -7,8 +7,8 @@ import ( "sync" "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/log" "github.com/docker/docker/errdefs" "github.com/docker/docker/libcontainerd" diff --git a/plugin/fetch_linux.go b/plugin/fetch_linux.go index 8d6b5af398..65f9cf2f8c 100644 --- a/plugin/fetch_linux.go +++ b/plugin/fetch_linux.go @@ -6,10 +6,10 @@ import ( "net/http" "time" - "github.com/containerd/containerd/content" - c8dimages "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/content" + c8dimages "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/plugin/manager.go b/plugin/manager.go index 86addb674e..9a02423b2f 100644 --- a/plugin/manager.go +++ b/plugin/manager.go @@ -12,8 +12,8 @@ import ( "sync" "syscall" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/containerd/log" "github.com/docker/docker/api/types" "github.com/docker/docker/api/types/events" diff --git a/plugin/manager_linux.go b/plugin/manager_linux.go index c674a1624c..fa44cca969 100644 --- a/plugin/manager_linux.go +++ b/plugin/manager_linux.go @@ -8,7 +8,7 @@ import ( "path/filepath" "time" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/log" "github.com/docker/docker/api/types" "github.com/docker/docker/daemon/initlayer" diff --git a/plugin/progress.go b/plugin/progress.go index ffe6c70aae..1ce33b3b70 100644 --- a/plugin/progress.go +++ b/plugin/progress.go @@ -4,7 +4,7 @@ import ( "sync" "time" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker" ) func newPushJobs(tracker docker.StatusTracker) *pushJobs { diff --git a/plugin/registry.go b/plugin/registry.go index f6921332b6..73f5f553a8 100644 --- a/plugin/registry.go +++ b/plugin/registry.go @@ -7,8 +7,8 @@ import ( "net/http" "time" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/containerd/log" "github.com/distribution/reference" "github.com/docker/docker/api/types/registry" diff --git a/vendor.mod b/vendor.mod index fafd3436ec..6abbc1052c 100644 --- a/vendor.mod +++ b/vendor.mod @@ -26,13 +26,13 @@ require ( github.com/aws/smithy-go v1.20.3 github.com/cloudflare/cfssl v1.6.4 github.com/containerd/cgroups/v3 v3.0.5 - github.com/containerd/containerd v1.7.25 github.com/containerd/containerd/api v1.8.0 + 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 github.com/containerd/log v0.1.0 - github.com/containerd/platforms v0.2.1 + github.com/containerd/platforms v1.0.0-rc.1 github.com/containerd/typeurl/v2 v2.2.3 github.com/coreos/go-systemd/v22 v22.5.0 github.com/cpuguy83/tar2go v0.3.1 @@ -63,7 +63,7 @@ require ( github.com/miekg/dns v1.1.57 github.com/mistifyio/go-zfs/v3 v3.0.1 github.com/mitchellh/copystructure v1.2.0 - github.com/moby/buildkit v0.18.2 + github.com/moby/buildkit v0.19.0-rc2 github.com/moby/docker-image-spec v1.3.1 github.com/moby/ipvs v1.1.0 github.com/moby/locker v1.0.1 @@ -145,8 +145,9 @@ require ( github.com/containerd/errdefs/pkg v0.3.0 // indirect github.com/containerd/go-cni v1.1.11 // indirect github.com/containerd/go-runc v1.1.0 // indirect - github.com/containerd/nydus-snapshotter v0.14.0 // indirect - github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect + github.com/containerd/nydus-snapshotter v0.15.0 // indirect + github.com/containerd/plugin v1.0.0 // indirect + github.com/containerd/stargz-snapshotter/estargz v0.16.3 // indirect github.com/containerd/ttrpc v1.2.7 // indirect github.com/containernetworking/cni v1.2.3 // indirect github.com/containernetworking/plugins v1.5.1 // indirect @@ -184,6 +185,7 @@ require ( github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opencontainers/runtime-tools v0.9.1-0.20221107090550-2e043c6bd626 // indirect github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 // indirect + github.com/pelletier/go-toml/v2 v2.2.3 // indirect github.com/philhofer/fwd v1.1.2 // indirect github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect @@ -198,8 +200,8 @@ require ( github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect github.com/tinylib/msgp v1.1.8 // indirect github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 // indirect - github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184 // indirect - github.com/tonistiigi/go-actions-cache v0.0.0-20241108014124-394979b8119e // indirect + github.com/tonistiigi/fsutil v0.0.0-20250113203817-b14e27f4135a // indirect + github.com/tonistiigi/go-actions-cache v0.0.0-20241210095730-017636a73805 // indirect github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 // indirect github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab // indirect @@ -234,3 +236,18 @@ require ( sigs.k8s.io/yaml v1.4.0 // indirect tags.cncf.io/container-device-interface/specs-go v0.8.0 // indirect ) + +exclude ( + // These dependencies were updated to "master" in some modules we depend on, + // but have no code-changes since their last release. Unfortunately, this also + // causes a ripple effect, forcing all users of the containerd module to also + // update these dependencies to an unrelease / un-tagged version. + // + // Both these dependencies will unlikely do a new release in the near future, + // so exclude these versions so that we can downgrade to the current release. + // + // For additional details, see this PR and links mentioned in that PR: + // https://github.com/kubernetes-sigs/kustomize/pull/5830#issuecomment-2569960859 + github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc + github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 +) diff --git a/vendor.sum b/vendor.sum index 36a6b2bebb..527480f85d 100644 --- a/vendor.sum +++ b/vendor.sum @@ -111,10 +111,10 @@ github.com/containerd/cgroups/v3 v3.0.5 h1:44na7Ud+VwyE7LIoJ8JTNQOa549a8543BmzaJ 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 v1.7.25 h1:khEQOAXOEJalRO228yzVsuASLH42vT7DIo9Ss+9SMFQ= -github.com/containerd/containerd v1.7.25/go.mod h1:tWfHzVI0azhw4CT2vaIjsb2CoV4LJ9PrMPaULAr21Ok= 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.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= @@ -129,12 +129,14 @@ github.com/containerd/go-runc v1.1.0 h1:OX4f+/i2y5sUT7LhmcJH7GYrjjhHa1QI4e8yO0gG github.com/containerd/go-runc v1.1.0/go.mod h1:xJv2hFF7GvHtTJd9JqTS2UVxMkULUYw4JN5XAUZqH5U= 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/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/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/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.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/estargz v0.16.3 h1:7evrXtoh1mSbGj/pfRccTampEyKpjpOnS3CyiV1Ebr8= +github.com/containerd/stargz-snapshotter/estargz v0.16.3/go.mod h1:uyr4BfYfOj3G9WBVE8cOlQmXAbPN9VEQpBBeJIuOipU= 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= @@ -365,8 +367,8 @@ github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:F github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= github.com/mndrix/tap-go v0.0.0-20171203230836-629fa407e90b/go.mod h1:pzzDgJWZ34fGzaAZGFW22KVZDfyrYW+QABMrWnJBnSs= -github.com/moby/buildkit v0.18.2 h1:l86uBvxh4ntNoUUg3Y0eGTbKg1PbUh6tawJ4Xt75SpQ= -github.com/moby/buildkit v0.18.2/go.mod h1:vCR5CX8NGsPTthTg681+9kdmfvkvqJBXEv71GZe5msU= +github.com/moby/buildkit v0.19.0-rc2 h1:7sAuQ5bDNIbdfmc7UDbrWJ2UPOR5w9rNWgnrEoC5aoo= +github.com/moby/buildkit v0.19.0-rc2/go.mod h1:4WYJLet/NI2p1o2rPQ6CIFpyyyvwvPz/TVISmwqqpHI= 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/ipvs v1.1.0 h1:ONN4pGaZQgAx+1Scz5RvWV4Q7Gb+mvfRh3NsPS+1XQQ= @@ -438,6 +440,8 @@ github.com/pascaldekloe/goe v0.1.0 h1:cBOtyMzM9HTpWjXfbbunk26uA6nG3a8n06Wieeh0Mw github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= 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.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= +github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee h1:P6U24L02WMfj9ymZTxl7CxS73JC99x3ukk+DBkgQGQs= github.com/phayes/permbits v0.0.0-20190612203442-39d7c581d2ee/go.mod h1:3uODdxMgOaPYeWU7RzZLxVtJHZ/x1f/iHkBZuKJDzuY= github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= @@ -525,10 +529,10 @@ github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw= github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 h1:eUk79E1w8yMtXeHSzjKorxuC8qJOnyXQnLaJehxpJaI= github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205/go.mod h1:3Iuxbr0P7D3zUzBMAZB+ois3h/et0shEz0qApgHYGpY= -github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184 h1:RgyoSI38Y36zjQaszel/0RAcIehAnjA1B0RiUV9SDO4= -github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184/go.mod h1:Dl/9oEjK7IqnjAm21Okx/XIxUCFJzvh+XdVHUlBwXTw= -github.com/tonistiigi/go-actions-cache v0.0.0-20241108014124-394979b8119e h1:SdcAL/tmv2mIfNhRygmeRrcci3aJQFqNughD7rcV170= -github.com/tonistiigi/go-actions-cache v0.0.0-20241108014124-394979b8119e/go.mod h1:xsu+XeKT9piH/5f9Y1Zsv5krQqI34CWkIusbs5027IM= +github.com/tonistiigi/fsutil v0.0.0-20250113203817-b14e27f4135a h1:EfGw4G0x/8qXWgtcZ6KVaPS+wpWOQMaypczzP8ojkMY= +github.com/tonistiigi/fsutil v0.0.0-20250113203817-b14e27f4135a/go.mod h1:Dl/9oEjK7IqnjAm21Okx/XIxUCFJzvh+XdVHUlBwXTw= +github.com/tonistiigi/go-actions-cache v0.0.0-20241210095730-017636a73805 h1:l2x1Ubj8f5xhPzZI428ZQ6+BDafGovpdk2ITnD3twTw= +github.com/tonistiigi/go-actions-cache v0.0.0-20241210095730-017636a73805/go.mod h1:xsu+XeKT9piH/5f9Y1Zsv5krQqI34CWkIusbs5027IM= github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0= github.com/tonistiigi/go-archvariant v1.0.0/go.mod h1:TxFmO5VS6vMq2kvs3ht04iPXtu2rUT/erOnGFYfk5Ho= github.com/tonistiigi/go-csvvalue v0.0.0-20240710180619-ddb21b71c0b4 h1:7I5c2Ig/5FgqkYOh/N87NzoyI9U15qUPXhDD8uCupv8= diff --git a/vendor/github.com/Microsoft/hcsshim/internal/vhdx/doc.go b/vendor/github.com/Microsoft/hcsshim/internal/vhdx/doc.go new file mode 100644 index 0000000000..99daaa288f --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/vhdx/doc.go @@ -0,0 +1,3 @@ +// vhdx package adds the utility methods necessary to deal with the vhdx that are used as the scratch +// space for the containers and the uvm. +package vhdx diff --git a/vendor/github.com/Microsoft/hcsshim/internal/vhdx/info.go b/vendor/github.com/Microsoft/hcsshim/internal/vhdx/info.go new file mode 100644 index 0000000000..4fc3bfd288 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/vhdx/info.go @@ -0,0 +1,233 @@ +//go:build windows + +package vhdx + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + "os" + "syscall" + "unsafe" + + "github.com/Microsoft/go-winio/pkg/guid" + "github.com/Microsoft/go-winio/vhd" + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/oc" + "github.com/sirupsen/logrus" + "go.opencensus.io/trace" + "golang.org/x/sys/windows" +) + +const _IOCTL_DISK_GET_DRIVE_LAYOUT_EX = 0x00070050 + +var partitionBasicDataGUID = guid.GUID{ + Data1: 0xebd0a0a2, + Data2: 0xb9e5, + Data3: 0x4433, + Data4: [8]byte{0x87, 0xc0, 0x68, 0xb6, 0xb7, 0x26, 0x99, 0xc7}, +} + +const ( + partitionStyleMBR uint32 = iota + partitionStyleGPT + partitionStyleRaw +) + +// type partitionInformationMBR struct { +// PartitionType uint8 +// BootIndicator uint8 +// RecognizedPartition uint8 +// HiddenSectors uint32 +// PartitionId guid.GUID +// } + +type partitionInformationGPT struct { + PartitionType guid.GUID + PartitionId guid.GUID + Attributes uint64 + Name [72]byte // wide char +} + +type partitionInformationEx struct { + PartitionStyle uint32 + StartingOffset int64 + PartitionLength int64 + PartitionNumber uint32 + RewritePartition uint8 + IsServicePartition uint8 + _ uint16 + // A union of partitionInformationMBR and partitionInformationGPT + // since partitionInformationGPT is largest with 112 bytes + GptMbrUnion [112]byte +} + +type driveLayoutInformationGPT struct { + DiskID guid.GUID + StartingUsableOffset int64 + UsableLength int64 + MaxPartitionCount uint32 +} + +// type driveLayoutInformationMBR struct { +// Signature uint32 +// Checksum uint32 +// } + +type driveLayoutInformationEx struct { + PartitionStyle uint32 + PartitionCount uint32 + // A union of driveLayoutInformationGPT and driveLayoutInformationMBR + // since driveLayoutInformationGPT is largest with 40 bytes + GptMbrUnion [40]byte + PartitionEntry [1]partitionInformationEx +} + +// Takes the physical path of a disk and retrieves the drive layout information of that disk. Returns the +// driveLayoutInformationEx struct and a slice of partitionInfomrationEx struct containing one element for +// each partition found on the vhdx. Note: some of the members like (GptMbrUnion) of these structs are raw +// byte arrays and it is the responsibility of the calling function to properly parse them. +func getDriveLayout(ctx context.Context, drivePhysicalPath string) (driveLayoutInformationEx, []partitionInformationEx, error) { + var ( + outBytes uint32 + err error + volume *os.File + ) + + layoutData := struct { + info driveLayoutInformationEx + // driveLayoutInformationEx has a flexible array member at the end. The data returned + // by IOCTL_DISK_GET_DRIVE_LAYOUT_EX usually has driveLayoutInformationEx.PartitionCount + // number of elements in this array. For all practical purposes we don't expect to have + // more than 64 partitions in a container/uvm vhdx. + partitions [63]partitionInformationEx + }{} + + volume, err = os.OpenFile(drivePhysicalPath, os.O_RDONLY, 0) + if err != nil { + return layoutData.info, layoutData.partitions[:0], fmt.Errorf("failed to open drive: %w", err) + } + defer volume.Close() + + err = windows.DeviceIoControl(windows.Handle(volume.Fd()), + _IOCTL_DISK_GET_DRIVE_LAYOUT_EX, + nil, + 0, + (*byte)(unsafe.Pointer(&layoutData)), + uint32(unsafe.Sizeof(layoutData)), + &outBytes, + nil) + if err != nil { + return layoutData.info, layoutData.partitions[:0], fmt.Errorf("IOCTL to get disk layout failed: %w", err) + } + + if layoutData.info.PartitionCount == 0 { + return layoutData.info, []partitionInformationEx{}, nil + } else { + // parse the retrieved data into driveLayoutInformationEx and partitionInformationEx + partitions := make([]partitionInformationEx, layoutData.info.PartitionCount) + partitions[0] = layoutData.info.PartitionEntry[0] + copy(partitions[1:], layoutData.partitions[:layoutData.info.PartitionCount-1]) + return layoutData.info, partitions, nil + } +} + +// Scratch VHDs are formatted with GPT style and have 1 MSFT_RESERVED +// partition and 1 BASIC_DATA partition. This struct contains the +// partitionID of this BASIC_DATA partition and the DiskID of this +// scratch vhdx. +type ScratchVhdxPartitionInfo struct { + DiskID guid.GUID + PartitionID guid.GUID +} + +// Returns the VhdxInfo of a GPT vhdx at path vhdxPath. +func GetScratchVhdPartitionInfo(ctx context.Context, vhdxPath string) (_ ScratchVhdxPartitionInfo, err error) { + var ( + diskHandle syscall.Handle + driveLayout driveLayoutInformationEx + partitions []partitionInformationEx + gptDriveLayout driveLayoutInformationGPT + gptPartitionInfo partitionInformationGPT + volumePath string + ) + + title := "hcsshim::GetScratchVhdPartitionInfo" + ctx, span := trace.StartSpan(ctx, title) + defer span.End() + defer func() { oc.SetSpanStatus(span, err) }() + span.AddAttributes( + trace.StringAttribute("path", vhdxPath)) + + diskHandle, err = vhd.OpenVirtualDisk(vhdxPath, vhd.VirtualDiskAccessNone, vhd.OpenVirtualDiskFlagNone) + if err != nil { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("get scratch vhd info failed: %w", err) + } + defer func() { + if closeErr := syscall.CloseHandle(diskHandle); closeErr != nil { + log.G(ctx).WithFields(logrus.Fields{ + "disk path": vhdxPath, + "error": closeErr, + }).Warn("failed to close vhd handle") + } + }() + + err = vhd.AttachVirtualDisk(diskHandle, vhd.AttachVirtualDiskFlagNone, &vhd.AttachVirtualDiskParameters{Version: 2}) + if err != nil { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("get scratch vhd info failed: %w", err) + } + + defer func() { + if detachErr := vhd.DetachVirtualDisk(diskHandle); detachErr != nil { + log.G(ctx).WithFields(logrus.Fields{ + "disk path": vhdxPath, + "error": detachErr, + }).Warn("failed to detach vhd") + } + }() + + volumePath, err = vhd.GetVirtualDiskPhysicalPath(diskHandle) + if err != nil { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("get vhd physical path: %w", err) + } + + driveLayout, partitions, err = getDriveLayout(ctx, volumePath) + if err != nil { + return ScratchVhdxPartitionInfo{}, err + } + + if driveLayout.PartitionStyle != partitionStyleGPT { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("drive Layout:Expected partition style GPT(%d) found %d", partitionStyleGPT, driveLayout.PartitionStyle) + } + + if driveLayout.PartitionCount != 2 || len(partitions) != 2 { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("expected exactly 2 partitions. Got %d partitions and partition count of %d", len(partitions), driveLayout.PartitionCount) + } + + if partitions[1].PartitionStyle != partitionStyleGPT { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("partition Info:Expected partition style GPT(%d) found %d", partitionStyleGPT, partitions[1].PartitionStyle) + } + + bufReader := bytes.NewBuffer(driveLayout.GptMbrUnion[:]) + if err := binary.Read(bufReader, binary.LittleEndian, &gptDriveLayout); err != nil { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("failed to parse drive GPT layout: %w", err) + } + + bufReader = bytes.NewBuffer(partitions[1].GptMbrUnion[:]) + if err := binary.Read(bufReader, binary.LittleEndian, &gptPartitionInfo); err != nil { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("failed to parse GPT partition info: %w", err) + } + + if gptPartitionInfo.PartitionType != partitionBasicDataGUID { + return ScratchVhdxPartitionInfo{}, fmt.Errorf("expected partition type to have %s GUID found %s instead", partitionBasicDataGUID, gptPartitionInfo.PartitionType) + } + + log.G(ctx).WithFields(logrus.Fields{ + "Disk ID": gptDriveLayout.DiskID, + "GPT Partition ID": gptPartitionInfo.PartitionId, + }).Debug("Scratch VHD partition info") + + return ScratchVhdxPartitionInfo{DiskID: gptDriveLayout.DiskID, PartitionID: gptPartitionInfo.PartitionId}, nil + +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/LayerWriter.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/LayerWriter.go new file mode 100644 index 0000000000..386cbcda9e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/LayerWriter.go @@ -0,0 +1,289 @@ +//go:build windows + +package cim + +import ( + "context" + "fmt" + "io" + "os" + "path/filepath" + "strconv" + "strings" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/oc" + "github.com/Microsoft/hcsshim/internal/wclayer" + "github.com/Microsoft/hcsshim/osversion" + "github.com/Microsoft/hcsshim/pkg/cimfs" + "go.opencensus.io/trace" +) + +// A CimLayerWriter implements the wclayer.LayerWriter interface to allow writing container +// image layers in the cim format. +// A cim layer consist of cim files (which are usually stored in the `cim-layers` directory and +// some other files which are stored in the directory of that layer (i.e the `path` directory). +type CimLayerWriter struct { + ctx context.Context + s *trace.Span + // path to the layer (i.e layer's directory) as provided by the caller. + // Even if a layer is stored as a cim in the cim directory, some files associated + // with a layer are still stored in this path. + path string + // parent layer paths + parentLayerPaths []string + // Handle to the layer cim - writes to the cim file + cimWriter *cimfs.CimFsWriter + // Handle to the writer for writing files in the local filesystem + stdFileWriter *stdFileWriter + // reference to currently active writer either cimWriter or stdFileWriter + activeWriter io.Writer + // denotes if this layer has the UtilityVM directory + hasUtilityVM bool + // some files are written outside the cim during initial import (via stdFileWriter) because we need to + // make some modifications to these files before writing them to the cim. The pendingOps slice + // maintains a list of such delayed modifications to the layer cim. These modifications are applied at + // the very end of layer import process. + pendingOps []pendingCimOp +} + +type hive struct { + name string + base string + delta string +} + +var ( + hives = []hive{ + {"SYSTEM", "SYSTEM_BASE", "SYSTEM_DELTA"}, + {"SOFTWARE", "SOFTWARE_BASE", "SOFTWARE_DELTA"}, + {"SAM", "SAM_BASE", "SAM_DELTA"}, + {"SECURITY", "SECURITY_BASE", "SECURITY_DELTA"}, + {"DEFAULT", "DEFAULTUSER_BASE", "DEFAULTUSER_DELTA"}, + } +) + +func isDeltaOrBaseHive(path string) bool { + for _, hv := range hives { + if strings.EqualFold(path, filepath.Join(wclayer.HivesPath, hv.delta)) || + strings.EqualFold(path, filepath.Join(wclayer.RegFilesPath, hv.name)) { + return true + } + } + return false +} + +// checks if this particular file should be written with a stdFileWriter instead of +// using the cimWriter. +func isStdFile(path string) bool { + return (isDeltaOrBaseHive(path) || + path == filepath.Join(wclayer.UtilityVMPath, wclayer.RegFilesPath, "SYSTEM") || + path == filepath.Join(wclayer.UtilityVMPath, wclayer.RegFilesPath, "SOFTWARE") || + path == wclayer.BcdFilePath || path == wclayer.BootMgrFilePath) +} + +// Add adds a file to the layer with given metadata. +func (cw *CimLayerWriter) Add(name string, fileInfo *winio.FileBasicInfo, fileSize int64, securityDescriptor []byte, extendedAttributes []byte, reparseData []byte) error { + if name == wclayer.UtilityVMPath { + cw.hasUtilityVM = true + } + if isStdFile(name) { + // create a pending op for this file + cw.pendingOps = append(cw.pendingOps, &addOp{ + pathInCim: name, + hostPath: filepath.Join(cw.path, name), + fileInfo: fileInfo, + securityDescriptor: securityDescriptor, + extendedAttributes: extendedAttributes, + reparseData: reparseData, + }) + if err := cw.stdFileWriter.Add(name); err != nil { + return err + } + cw.activeWriter = cw.stdFileWriter + } else { + if err := cw.cimWriter.AddFile(name, fileInfo, fileSize, securityDescriptor, extendedAttributes, reparseData); err != nil { + return err + } + cw.activeWriter = cw.cimWriter + } + return nil +} + +// AddLink adds a hard link to the layer. The target must already have been added. +func (cw *CimLayerWriter) AddLink(name string, target string) error { + // set active write to nil so that we panic if layer tar is incorrectly formatted. + cw.activeWriter = nil + if isStdFile(target) { + // If this is a link to a std file it will have to be added later once the + // std file is written to the CIM. Create a pending op for this + cw.pendingOps = append(cw.pendingOps, &linkOp{ + oldPath: target, + newPath: name, + }) + return nil + } else if isStdFile(name) { + // None of the predefined std files are links. If they show up as links this is unexpected + // behavior. Error out. + return fmt.Errorf("unexpected link %s in layer", name) + } else { + return cw.cimWriter.AddLink(target, name) + } +} + +// AddAlternateStream creates another alternate stream at the given +// path. Any writes made after this call will go to that stream. +func (cw *CimLayerWriter) AddAlternateStream(name string, size uint64) error { + if isStdFile(name) { + // As of now there is no known case of std file having multiple data streams. + // If such a file is encountered our assumptions are wrong. Error out. + return fmt.Errorf("unexpected alternate stream %s in layer", name) + } + + if err := cw.cimWriter.CreateAlternateStream(name, size); err != nil { + return err + } + cw.activeWriter = cw.cimWriter + return nil +} + +// Remove removes a file that was present in a parent layer from the layer. +func (cw *CimLayerWriter) Remove(name string) error { + // set active write to nil so that we panic if layer tar is incorrectly formatted. + cw.activeWriter = nil + return cw.cimWriter.Unlink(name) +} + +// Write writes data to the current file. The data must be in the format of a Win32 +// backup stream. +func (cw *CimLayerWriter) Write(b []byte) (int, error) { + return cw.activeWriter.Write(b) +} + +// Close finishes the layer writing process and releases any resources. +func (cw *CimLayerWriter) Close(ctx context.Context) (retErr error) { + if err := cw.stdFileWriter.Close(ctx); err != nil { + return err + } + + // cimWriter must be closed even if there are errors. + defer func() { + if err := cw.cimWriter.Close(); retErr == nil { + retErr = err + } + }() + + // Find out the osversion of this layer, both base & non-base layers can have UtilityVM layer. + processUtilityVM := false + if cw.hasUtilityVM { + uvmSoftwareHivePath := filepath.Join(cw.path, wclayer.UtilityVMPath, wclayer.RegFilesPath, "SOFTWARE") + osvStr, err := getOsBuildNumberFromRegistry(uvmSoftwareHivePath) + if err != nil { + return fmt.Errorf("read os version string from UtilityVM SOFTWARE hive: %w", err) + } + + osv, err := strconv.ParseUint(osvStr, 10, 16) + if err != nil { + return fmt.Errorf("parse os version string (%s): %w", osvStr, err) + } + + // write this version to a file for future reference by the shim process + if err = wclayer.WriteLayerUvmBuildFile(cw.path, uint16(osv)); err != nil { + return fmt.Errorf("write uvm build version: %w", err) + } + + // CIMFS for hyperV isolated is only supported after 20348, processing UtilityVM layer on 2048 + // & lower will cause failures since those images won't have CIMFS specific UVM files (mostly + // BCD entries required for CIMFS) + processUtilityVM = (osv > osversion.LTSC2022) + log.G(ctx).Debugf("import image os version %d, processing UtilityVM layer: %t\n", osv, processUtilityVM) + } + + if len(cw.parentLayerPaths) == 0 { + if err := cw.processBaseLayer(ctx, processUtilityVM); err != nil { + return fmt.Errorf("process base layer: %w", err) + } + } else { + if err := cw.processNonBaseLayer(ctx, processUtilityVM); err != nil { + return fmt.Errorf("process non base layer: %w", err) + } + } + + for _, op := range cw.pendingOps { + if err := op.apply(cw.cimWriter); err != nil { + return fmt.Errorf("apply pending operations: %w", err) + } + } + return nil +} + +func NewCimLayerWriter(ctx context.Context, path string, parentLayerPaths []string) (_ *CimLayerWriter, err error) { + if !cimfs.IsCimFSSupported() { + return nil, fmt.Errorf("CimFs not supported on this build") + } + + ctx, span := trace.StartSpan(ctx, "hcsshim::NewCimLayerWriter") + defer func() { + if err != nil { + oc.SetSpanStatus(span, err) + span.End() + } + }() + span.AddAttributes( + trace.StringAttribute("path", path), + trace.StringAttribute("parentLayerPaths", strings.Join(parentLayerPaths, ", "))) + + parentCim := "" + cimDirPath := GetCimDirFromLayer(path) + if _, err = os.Stat(cimDirPath); os.IsNotExist(err) { + // create cim directory + if err = os.Mkdir(cimDirPath, 0755); err != nil { + return nil, fmt.Errorf("failed while creating cim layers directory: %w", err) + } + } else if err != nil { + return nil, fmt.Errorf("unable to access cim layers directory: %w", err) + + } + + if len(parentLayerPaths) > 0 { + parentCim = GetCimNameFromLayer(parentLayerPaths[0]) + } + + cim, err := cimfs.Create(cimDirPath, parentCim, GetCimNameFromLayer(path)) + if err != nil { + return nil, fmt.Errorf("error in creating a new cim: %w", err) + } + + sfw, err := newStdFileWriter(path, parentLayerPaths) + if err != nil { + return nil, fmt.Errorf("error in creating new standard file writer: %w", err) + } + return &CimLayerWriter{ + ctx: ctx, + s: span, + path: path, + parentLayerPaths: parentLayerPaths, + cimWriter: cim, + stdFileWriter: sfw, + }, nil +} + +// DestroyCimLayer destroys a cim layer i.e it removes all the cimfs files for the given layer as well as +// all of the other files that are stored in the layer directory (at path `layerPath`). +// If this is not a cimfs layer (i.e a cim file for the given layer does not exist) then nothing is done. +func DestroyCimLayer(ctx context.Context, layerPath string) error { + cimPath := GetCimPathFromLayer(layerPath) + + // verify that such a cim exists first, sometimes containerd tries to call + // this with the root snapshot directory as the layer path. We don't want to + // destroy everything inside the snapshots directory. + if _, err := os.Stat(cimPath); err != nil { + if os.IsNotExist(err) { + return nil + } + return err + } + + return cimfs.DestroyCim(ctx, cimPath) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/bcd.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/bcd.go new file mode 100644 index 0000000000..23a3ce6776 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/bcd.go @@ -0,0 +1,107 @@ +//go:build windows + +package cim + +import ( + "bytes" + "fmt" + "os/exec" + + "github.com/Microsoft/go-winio/pkg/guid" +) + +const ( + bcdFilePath = "UtilityVM\\Files\\EFI\\Microsoft\\Boot\\BCD" + cimfsDeviceOptionsID = "{763e9fea-502d-434f-aad9-5fabe9c91a7b}" + vmbusDeviceID = "{c63c9bdf-5fa5-4208-b03f-6b458b365592}" + compositeDeviceOptionsID = "{e1787220-d17f-49e7-977a-d8fe4c8537e2}" + bootContainerID = "{b890454c-80de-4e98-a7ab-56b74b4fbd0c}" +) + +func bcdExec(storePath string, args ...string) error { + var out bytes.Buffer + argsArr := []string{"/store", storePath, "/offline"} + argsArr = append(argsArr, args...) + cmd := exec.Command("bcdedit.exe", argsArr...) + cmd.Stdout = &out + if err := cmd.Run(); err != nil { + return fmt.Errorf("bcd command (%s) failed: %w", cmd, err) + } + return nil +} + +// A registry configuration required for the uvm. +func setBcdRestartOnFailure(storePath string) error { + return bcdExec(storePath, "/set", "{default}", "restartonfailure", "yes") +} + +func setBcdCimBootDevice(storePath, cimPathRelativeToVSMB string, diskID, partitionID guid.GUID) error { + // create options for cimfs boot device + if err := bcdExec(storePath, "/create", cimfsDeviceOptionsID, "/d", "CimFS Device Options", "/device"); err != nil { + return err + } + + // Set options. For now we need to set 2 options. First is the parent device i.e the device under + // which all cim files will be available. Second is the path of the cim (from which this UVM should + // boot) relative to the parent device. Note that even though the 2nd option is named + // `cimfsrootdirectory` it expects a path to the cim file and not a directory path. + if err := bcdExec(storePath, "/set", cimfsDeviceOptionsID, "cimfsparentdevice", fmt.Sprintf("vmbus=%s", vmbusDeviceID)); err != nil { + return err + } + + if err := bcdExec(storePath, "/set", cimfsDeviceOptionsID, "cimfsrootdirectory", fmt.Sprintf("\\%s", cimPathRelativeToVSMB)); err != nil { + return err + } + + // create options for the composite device + if err := bcdExec(storePath, "/create", compositeDeviceOptionsID, "/d", "Composite Device Options", "/device"); err != nil { + return err + } + + // We need to specify the diskID & the partition ID of the boot disk and we need to set the cimfs boot + // options ID + partitionStr := fmt.Sprintf("gpt_partition={%s};{%s}", diskID, partitionID) + if err := bcdExec(storePath, "/set", compositeDeviceOptionsID, "primarydevice", partitionStr); err != nil { + return err + } + + if err := bcdExec(storePath, "/set", compositeDeviceOptionsID, "secondarydevice", fmt.Sprintf("cimfs=%s,%s", bootContainerID, cimfsDeviceOptionsID)); err != nil { + return err + } + + if err := bcdExec(storePath, "/set", "{default}", "device", fmt.Sprintf("composite=0,%s", compositeDeviceOptionsID)); err != nil { + return err + } + + if err := bcdExec(storePath, "/set", "{default}", "osdevice", fmt.Sprintf("composite=0,%s", compositeDeviceOptionsID)); err != nil { + return err + } + + // Since our UVM file are stored under UtilityVM\Files directory inside the CIM we must prepend that + // directory in front of paths used by bootmgr + if err := bcdExec(storePath, "/set", "{default}", "path", "\\UtilityVM\\Files\\Windows\\System32\\winload.efi"); err != nil { + return err + } + + if err := bcdExec(storePath, "/set", "{default}", "systemroot", "\\UtilityVM\\Files\\Windows"); err != nil { + return err + } + + return nil +} + +// updateBcdStoreForBoot Updates the bcd store at path layerPath + UtilityVM\Files\EFI\Microsoft\Boot\BCD` to +// boot with the disk with given ID and given partitionID. cimPathRelativeToVSMB is the path of the cim which +// will be used for booting this UVM relative to the VSMB share. (Usually, the entire snapshots directory will +// be shared over VSMB, so if this is the cim-layers\1.cim under that directory, the value of +// `cimPathRelativeToVSMB` should be cim-layers\1.cim) +func updateBcdStoreForBoot(storePath string, cimPathRelativeToVSMB string, diskID, partitionID guid.GUID) error { + if err := setBcdRestartOnFailure(storePath); err != nil { + return err + } + + if err := setBcdCimBootDevice(storePath, cimPathRelativeToVSMB, diskID, partitionID); err != nil { + return err + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/common.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/common.go new file mode 100644 index 0000000000..bdeebd3c03 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/common.go @@ -0,0 +1,41 @@ +//go:build windows + +package cim + +import ( + "os" + "path/filepath" +) + +const ( + // name of the directory in which cims are stored + cimDir = "cim-layers" +) + +// Usually layers are stored at ./root/io.containerd.snapshotter.v1.windows/snapshots/. For cimfs we +// must store all layer cims in the same directory (for forked cims to work). So all cim layers are stored in +// /root/io.containerd.snapshotter.v1.windows/snapshots/cim-layers. And the cim file representing each +// individual layer is stored at /root/io.containerd.snapshotter.v1.windows/snapshots/cim-layers/.cim + +// CimName is the filename (.cim) of the file representing the cim +func GetCimNameFromLayer(layerPath string) string { + return filepath.Base(layerPath) + ".cim" +} + +// CimPath is the path to the CimDir/.cim file that represents a layer cim. +func GetCimPathFromLayer(layerPath string) string { + return filepath.Join(GetCimDirFromLayer(layerPath), GetCimNameFromLayer(layerPath)) +} + +// CimDir is the directory inside which all cims are stored. +func GetCimDirFromLayer(layerPath string) string { + dir := filepath.Dir(layerPath) + return filepath.Join(dir, cimDir) +} + +// IsCimLayer returns `true` if the layer at path `layerPath` is a cim layer. Returns `false` otherwise. +func IsCimLayer(layerPath string) bool { + cimPath := GetCimPathFromLayer(layerPath) + _, err := os.Stat(cimPath) + return (err == nil) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/doc.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/doc.go new file mode 100644 index 0000000000..d814659965 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/doc.go @@ -0,0 +1,3 @@ +// This package provides utilities for working with container image layers in the cim format +// via the wclayer APIs. +package cim diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/file_writer.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/file_writer.go new file mode 100644 index 0000000000..497bbbbb9a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/file_writer.go @@ -0,0 +1,90 @@ +//go:build windows + +package cim + +import ( + "context" + "fmt" + "os" + "path/filepath" + "syscall" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/safefile" + "github.com/Microsoft/hcsshim/internal/winapi" +) + +// stdFileWriter writes the files of a layer to the layer folder instead of writing them inside the cim. +// For some files (like the Hive files or some UtilityVM files) it is necessary to write them as a normal file +// first, do some modifications on them (for example merging of hives or processing of UtilityVM files) +// and then write the modified versions into the cim. This writer is used for such files. +type stdFileWriter struct { + activeFile *os.File + // parent layer paths + parentLayerPaths []string + // path to the current layer + path string + // the open handle to the path directory + root *os.File +} + +func newStdFileWriter(root string, parentRoots []string) (sfw *stdFileWriter, err error) { + sfw = &stdFileWriter{ + path: root, + parentLayerPaths: parentRoots, + } + sfw.root, err = safefile.OpenRoot(root) + if err != nil { + return + } + return +} + +func (sfw *stdFileWriter) closeActiveFile() (err error) { + if sfw.activeFile != nil { + err = sfw.activeFile.Close() + sfw.activeFile = nil + } + return +} + +// Adds a new file or an alternate data stream to an existing file inside the layer directory. +func (sfw *stdFileWriter) Add(name string) error { + if err := sfw.closeActiveFile(); err != nil { + return err + } + + // The directory of this file might be created inside the cim. + // make sure we have the same parent directory chain here + if err := safefile.MkdirAllRelative(filepath.Dir(name), sfw.root); err != nil { + return fmt.Errorf("failed to create file %s: %w", name, err) + } + + f, err := safefile.OpenRelative( + name, + sfw.root, + syscall.GENERIC_READ|syscall.GENERIC_WRITE|winio.WRITE_DAC|winio.WRITE_OWNER, + syscall.FILE_SHARE_READ, + winapi.FILE_CREATE, + 0, + ) + if err != nil { + return fmt.Errorf("error creating file %s: %w", name, err) + } + sfw.activeFile = f + return nil +} + +// Write writes data to the current file. The data must be in the format of a Win32 +// backup stream. +func (sfw *stdFileWriter) Write(b []byte) (int, error) { + return sfw.activeFile.Write(b) +} + +// Close finishes the layer writing process and releases any resources. +func (sfw *stdFileWriter) Close(ctx context.Context) error { + if err := sfw.closeActiveFile(); err != nil { + return fmt.Errorf("failed to close active file %s : %w", sfw.activeFile.Name(), err) + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/mount.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/mount.go new file mode 100644 index 0000000000..22f21dd43a --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/mount.go @@ -0,0 +1,89 @@ +//go:build windows + +package cim + +import ( + "context" + "fmt" + "os" + "sync" + + "github.com/Microsoft/go-winio/pkg/guid" + hcsschema "github.com/Microsoft/hcsshim/internal/hcs/schema2" + cimfs "github.com/Microsoft/hcsshim/pkg/cimfs" +) + +// a cache of cim layer to its mounted volume - The mount manager plugin currently doesn't have an option of +// querying a mounted cim to get the volume at which it is mounted, so we maintain a cache of that here +var ( + cimMounts map[string]string = make(map[string]string) + cimMountMapLock sync.Mutex + // A random GUID used as a namespace for generating cim mount volume GUIDs: 6827367b-c388-4e9b-95ec-961c6d2c936c + cimMountNamespace guid.GUID = guid.GUID{Data1: 0x6827367b, Data2: 0xc388, Data3: 0x4e9b, Data4: [8]byte{0x96, 0x1c, 0x6d, 0x2c, 0x93, 0x6c}} +) + +// MountCimLayer mounts the cim at path `cimPath` and returns the mount location of that cim. This method +// uses the `CimMountFlagCacheFiles` mount flag when mounting the cim. The containerID is used to generated +// the volumeID for the volume at which this CIM is mounted. containerID is used so that if the shim process +// crashes for any reason, the mounted cim can be correctly cleaned up during `shim delete` call. +func MountCimLayer(ctx context.Context, cimPath, containerID string) (string, error) { + volumeGUID, err := guid.NewV5(cimMountNamespace, []byte(containerID)) + if err != nil { + return "", fmt.Errorf("generated cim mount GUID: %w", err) + } + + vol, err := cimfs.Mount(cimPath, volumeGUID, hcsschema.CimMountFlagCacheFiles) + if err != nil { + return "", err + } + + cimMountMapLock.Lock() + defer cimMountMapLock.Unlock() + cimMounts[fmt.Sprintf("%s_%s", containerID, cimPath)] = vol + + return vol, nil +} + +// Unmount unmounts the cim at mounted for given container. +func UnmountCimLayer(ctx context.Context, cimPath, containerID string) error { + cimMountMapLock.Lock() + defer cimMountMapLock.Unlock() + if vol, ok := cimMounts[fmt.Sprintf("%s_%s", containerID, cimPath)]; !ok { + return fmt.Errorf("cim %s not mounted", cimPath) + } else { + delete(cimMounts, fmt.Sprintf("%s_%s", containerID, cimPath)) + err := cimfs.Unmount(vol) + if err != nil { + return err + } + } + return nil +} + +// GetCimMountPath returns the volume at which a cim is mounted. If the cim is not mounted returns error +func GetCimMountPath(cimPath, containerID string) (string, error) { + cimMountMapLock.Lock() + defer cimMountMapLock.Unlock() + + if vol, ok := cimMounts[fmt.Sprintf("%s_%s", containerID, cimPath)]; !ok { + return "", fmt.Errorf("cim %s not mounted", cimPath) + } else { + return vol, nil + } +} + +func CleanupContainerMounts(containerID string) error { + volumeGUID, err := guid.NewV5(cimMountNamespace, []byte(containerID)) + if err != nil { + return fmt.Errorf("generated cim mount GUID: %w", err) + } + + volPath := fmt.Sprintf("\\\\?\\Volume{%s}\\", volumeGUID.String()) + if _, err := os.Stat(volPath); err == nil { + err = cimfs.Unmount(volPath) + if err != nil { + return err + } + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/pending.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/pending.go new file mode 100644 index 0000000000..d13bdff850 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/pending.go @@ -0,0 +1,68 @@ +//go:build windows + +package cim + +import ( + "fmt" + "io" + "os" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/pkg/cimfs" + "golang.org/x/sys/windows" +) + +type pendingCimOp interface { + apply(cw *cimfs.CimFsWriter) error +} + +// add op represents a pending operation of adding a new file inside the cim +type addOp struct { + // path inside the cim at which the file should be added + pathInCim string + // host path where this file was temporarily written. + hostPath string + // other file metadata fields that were provided during the add call. + fileInfo *winio.FileBasicInfo + securityDescriptor []byte + extendedAttributes []byte + reparseData []byte +} + +func (o *addOp) apply(cw *cimfs.CimFsWriter) error { + f, err := os.Open(o.hostPath) + if err != nil { + return fmt.Errorf("open file %s: %w", o.hostPath, err) + } + defer f.Close() + + fs, err := f.Stat() + if err != nil { + return fmt.Errorf("stat file %s: %w", o.hostPath, err) + } + + if err := cw.AddFile(o.pathInCim, o.fileInfo, fs.Size(), o.securityDescriptor, o.extendedAttributes, o.reparseData); err != nil { + return fmt.Errorf("cim add file %s: %w", o.hostPath, err) + } + + if o.fileInfo.FileAttributes != windows.FILE_ATTRIBUTE_DIRECTORY { + written, err := io.Copy(cw, f) + if err != nil { + return fmt.Errorf("write file %s inside cim: %w", o.hostPath, err) + } else if written != fs.Size() { + return fmt.Errorf("short write to cim for file %s, expected %d bytes wrote %d", o.hostPath, fs.Size(), written) + } + } + return nil +} + +// linkOp represents a pending link file operation inside the cim +type linkOp struct { + // old & new paths inside the cim where the link should be created + oldPath string + newPath string +} + +func (o *linkOp) apply(cw *cimfs.CimFsWriter) error { + return cw.AddLink(o.oldPath, o.newPath) +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/process.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/process.go new file mode 100644 index 0000000000..9ed0428b7e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/process.go @@ -0,0 +1,230 @@ +//go:build windows + +package cim + +import ( + "context" + "fmt" + "os" + "path/filepath" + "syscall" + "time" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/go-winio/vhd" + "github.com/Microsoft/hcsshim/computestorage" + "github.com/Microsoft/hcsshim/internal/memory" + "github.com/Microsoft/hcsshim/internal/security" + "github.com/Microsoft/hcsshim/internal/vhdx" + "github.com/Microsoft/hcsshim/internal/wclayer" + "golang.org/x/sys/windows" +) + +const defaultVHDXBlockSizeInMB = 1 + +// processUtilityVMLayer is similar to createContainerBaseLayerVHDs but along with the scratch creation it +// also does some BCD modifications to allow the UVM to boot from the CIM. It expects that the UVM BCD file is +// present at layerPath/`wclayer.BcdFilePath` and a UVM SYSTEM hive is present at +// layerPath/UtilityVM/`wclayer.RegFilesPath`/SYSTEM. The scratch VHDs are created under the `layerPath` +// directory. +func processUtilityVMLayer(ctx context.Context, layerPath string) error { + // func createUtilityVMLayerVHDs(ctx context.Context, layerPath string) error { + baseVhdPath := filepath.Join(layerPath, wclayer.UtilityVMPath, wclayer.UtilityVMBaseVhd) + diffVhdPath := filepath.Join(layerPath, wclayer.UtilityVMPath, wclayer.UtilityVMScratchVhd) + defaultVhdSize := uint64(10) + + // Just create the vhdx for utilityVM layer, no need to format it. + createParams := &vhd.CreateVirtualDiskParameters{ + Version: 2, + Version2: vhd.CreateVersion2{ + MaximumSize: defaultVhdSize * memory.GiB, + BlockSizeInBytes: defaultVHDXBlockSizeInMB * memory.MiB, + }, + } + + handle, err := vhd.CreateVirtualDisk(baseVhdPath, vhd.VirtualDiskAccessNone, vhd.CreateVirtualDiskFlagNone, createParams) + if err != nil { + return fmt.Errorf("failed to create vhdx: %w", err) + } + + defer func() { + if err != nil { + os.RemoveAll(baseVhdPath) + os.RemoveAll(diffVhdPath) + } + }() + + err = computestorage.FormatWritableLayerVhd(ctx, windows.Handle(handle)) + closeErr := syscall.CloseHandle(handle) + if err != nil { + return err + } else if closeErr != nil { + return fmt.Errorf("failed to close vhdx handle: %w", closeErr) + } + + partitionInfo, err := vhdx.GetScratchVhdPartitionInfo(ctx, baseVhdPath) + if err != nil { + return fmt.Errorf("failed to get base vhd layout info: %w", err) + } + // relativeCimPath needs to be the cim path relative to the snapshots directory. The snapshots + // directory is shared inside the UVM over VSMB, so during the UVM boot this relative path will be + // used to find the cim file under that VSMB share. + relativeCimPath := filepath.Join(filepath.Base(GetCimDirFromLayer(layerPath)), GetCimNameFromLayer(layerPath)) + bcdPath := filepath.Join(layerPath, bcdFilePath) + if err = updateBcdStoreForBoot(bcdPath, relativeCimPath, partitionInfo.DiskID, partitionInfo.PartitionID); err != nil { + return fmt.Errorf("failed to update BCD: %w", err) + } + + if err := enableCimBoot(filepath.Join(layerPath, wclayer.UtilityVMPath, wclayer.RegFilesPath, "SYSTEM")); err != nil { + return fmt.Errorf("failed to setup cim image for uvm boot: %w", err) + } + + // Note: diff vhd creation and granting of vm group access must be done AFTER + // getting the partition info of the base VHD. Otherwise it causes the vhd parent + // chain to get corrupted. + // TODO(ambarve): figure out why this happens so that bcd update can be moved to a separate function + + // Create the differencing disk that will be what's copied for the final rw layer + // for a container. + if err = vhd.CreateDiffVhd(diffVhdPath, baseVhdPath, defaultVHDXBlockSizeInMB); err != nil { + return fmt.Errorf("failed to create differencing disk: %w", err) + } + + if err := security.GrantVmGroupAccess(baseVhdPath); err != nil { + return fmt.Errorf("failed to grant vm group access to %s: %w", baseVhdPath, err) + } + if err := security.GrantVmGroupAccess(diffVhdPath); err != nil { + return fmt.Errorf("failed to grant vm group access to %s: %w", diffVhdPath, err) + } + return nil +} + +// processBaseLayerHives make the base layer specific modifications on the hives and emits equivalent the +// pendingCimOps that should be applied on the CIM. In base layer we need to create hard links from registry +// hives under Files/Windows/Sysetm32/config into Hives/*_BASE. This function creates these links outside so +// that the registry hives under Hives/ are available during children layers import. Then we write these hive +// files inside the cim and create links inside the cim. +func processBaseLayerHives(layerPath string) ([]pendingCimOp, error) { + pendingOps := []pendingCimOp{} + + // make hives directory both outside and in the cim + if err := os.Mkdir(filepath.Join(layerPath, wclayer.HivesPath), 0755); err != nil { + return pendingOps, fmt.Errorf("hives directory creation: %w", err) + } + + hivesDirInfo := &winio.FileBasicInfo{ + CreationTime: windows.NsecToFiletime(time.Now().UnixNano()), + LastAccessTime: windows.NsecToFiletime(time.Now().UnixNano()), + LastWriteTime: windows.NsecToFiletime(time.Now().UnixNano()), + ChangeTime: windows.NsecToFiletime(time.Now().UnixNano()), + FileAttributes: windows.FILE_ATTRIBUTE_DIRECTORY, + } + pendingOps = append(pendingOps, &addOp{ + pathInCim: wclayer.HivesPath, + hostPath: filepath.Join(layerPath, wclayer.HivesPath), + fileInfo: hivesDirInfo, + }) + + // add hard links from base hive files. + for _, hv := range hives { + oldHivePathRelative := filepath.Join(wclayer.RegFilesPath, hv.name) + newHivePathRelative := filepath.Join(wclayer.HivesPath, hv.base) + if err := os.Link(filepath.Join(layerPath, oldHivePathRelative), filepath.Join(layerPath, newHivePathRelative)); err != nil { + return pendingOps, fmt.Errorf("hive link creation: %w", err) + } + + pendingOps = append(pendingOps, &linkOp{ + oldPath: oldHivePathRelative, + newPath: newHivePathRelative, + }) + } + return pendingOps, nil +} + +// processLayoutFile creates a file named "layout" in the root of the base layer. This allows certain +// container startup related functions to understand that the hives are a part of the container rootfs. +func processLayoutFile(layerPath string) ([]pendingCimOp, error) { + fileContents := "vhd-with-hives\n" + if err := os.WriteFile(filepath.Join(layerPath, "layout"), []byte(fileContents), 0755); err != nil { + return []pendingCimOp{}, fmt.Errorf("write layout file: %w", err) + } + + layoutFileInfo := &winio.FileBasicInfo{ + CreationTime: windows.NsecToFiletime(time.Now().UnixNano()), + LastAccessTime: windows.NsecToFiletime(time.Now().UnixNano()), + LastWriteTime: windows.NsecToFiletime(time.Now().UnixNano()), + ChangeTime: windows.NsecToFiletime(time.Now().UnixNano()), + FileAttributes: windows.FILE_ATTRIBUTE_NORMAL, + } + + op := &addOp{ + pathInCim: "layout", + hostPath: filepath.Join(layerPath, "layout"), + fileInfo: layoutFileInfo, + } + return []pendingCimOp{op}, nil +} + +// Some of the layer files that are generated during the processBaseLayer call must be added back +// inside the cim, some registry file links must be updated. This function takes care of all those +// steps. This function opens the cim file for writing and updates it. +func (cw *CimLayerWriter) processBaseLayer(ctx context.Context, processUtilityVM bool) (err error) { + if processUtilityVM { + if err = processUtilityVMLayer(ctx, cw.path); err != nil { + return fmt.Errorf("process utilityVM layer: %w", err) + } + } + + ops, err := processBaseLayerHives(cw.path) + if err != nil { + return err + } + cw.pendingOps = append(cw.pendingOps, ops...) + + ops, err = processLayoutFile(cw.path) + if err != nil { + return err + } + cw.pendingOps = append(cw.pendingOps, ops...) + return nil +} + +// processNonBaseLayer takes care of the processing required for a non base layer. As of now +// the only processing required for non base layer is to merge the delta registry hives of the +// non-base layer with it's parent layer. +func (cw *CimLayerWriter) processNonBaseLayer(ctx context.Context, processUtilityVM bool) (err error) { + for _, hv := range hives { + baseHive := filepath.Join(wclayer.HivesPath, hv.base) + deltaHive := filepath.Join(wclayer.HivesPath, hv.delta) + _, err := os.Stat(filepath.Join(cw.path, deltaHive)) + // merge with parent layer if delta exists. + if err != nil && !os.IsNotExist(err) { + return fmt.Errorf("stat delta hive %s: %w", filepath.Join(cw.path, deltaHive), err) + } else if err == nil { + // merge base hive of parent layer with the delta hive of this layer and write it as + // the base hive of this layer. + err = mergeHive(filepath.Join(cw.parentLayerPaths[0], baseHive), filepath.Join(cw.path, deltaHive), filepath.Join(cw.path, baseHive)) + if err != nil { + return err + } + + // the newly created merged file must be added to the cim + cw.pendingOps = append(cw.pendingOps, &addOp{ + pathInCim: baseHive, + hostPath: filepath.Join(cw.path, baseHive), + fileInfo: &winio.FileBasicInfo{ + CreationTime: windows.NsecToFiletime(time.Now().UnixNano()), + LastAccessTime: windows.NsecToFiletime(time.Now().UnixNano()), + LastWriteTime: windows.NsecToFiletime(time.Now().UnixNano()), + ChangeTime: windows.NsecToFiletime(time.Now().UnixNano()), + FileAttributes: windows.FILE_ATTRIBUTE_NORMAL, + }, + }) + } + } + + if processUtilityVM { + return processUtilityVMLayer(ctx, cw.path) + } + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/registry.go b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/registry.go new file mode 100644 index 0000000000..dd2af81cf3 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/internal/wclayer/cim/registry.go @@ -0,0 +1,172 @@ +//go:build windows + +package cim + +import ( + "encoding/binary" + "fmt" + "os" + "unsafe" + + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/winapi" + "github.com/Microsoft/hcsshim/osversion" + "github.com/pkg/errors" + "github.com/sirupsen/logrus" + "golang.org/x/sys/windows" +) + +// enableCimBoot Opens the SYSTEM registry hive at path `hivePath` and updates it to include a CIMFS Start +// registry key. This prepares the uvm to boot from a cim file if requested. The registry changes required to +// actually make the uvm boot from a cim will be added in the uvm config (look at +// addBootFromCimRegistryChanges for details). This registry key needs to be available in the early boot +// phase and so including it in the uvm config doesn't work. +func enableCimBoot(hivePath string) (err error) { + dataZero := make([]byte, 4) + dataOne := make([]byte, 4) + binary.LittleEndian.PutUint32(dataOne, 1) + dataFour := make([]byte, 4) + binary.LittleEndian.PutUint32(dataFour, 4) + + bootGUID, err := windows.UTF16FromString(bootContainerID) + if err != nil { + return fmt.Errorf("failed to encode boot guid to utf16: %w", err) + } + + overrideBootPath, err := windows.UTF16FromString("\\Windows\\") + if err != nil { + return fmt.Errorf("failed to encode override boot path to utf16: %w", err) + } + + regChanges := []struct { + keyPath string + valueName string + valueType winapi.RegType + data *byte + dataLen uint32 + }{ + {"ControlSet001\\Control", "BootContainerGuid", winapi.REG_TYPE_SZ, (*byte)(unsafe.Pointer(&bootGUID[0])), 2 * uint32(len(bootGUID))}, + {"ControlSet001\\Services\\UnionFS", "Start", winapi.REG_TYPE_DWORD, &dataZero[0], uint32(len(dataZero))}, + {"ControlSet001\\Services\\wcifs", "Start", winapi.REG_TYPE_DWORD, &dataFour[0], uint32(len(dataZero))}, + // The bootmgr loads the uvm files from the cim and so uses the relative path `UtilityVM\\Files` inside the cim to access the uvm files. However, once the cim is mounted UnionFS will merge the correct directory (UtilityVM\\Files) of the cim with the scratch and then that point onwards we don't need to use the relative path. Below registry key tells the kernel that the boot path that was provided in BCD should now be overriden with this new path. + {"Setup", "BootPathOverride", winapi.REG_TYPE_SZ, (*byte)(unsafe.Pointer(&overrideBootPath[0])), 2 * uint32(len(overrideBootPath))}, + } + + var storeHandle winapi.ORHKey + if err = winapi.OROpenHive(hivePath, &storeHandle); err != nil { + return fmt.Errorf("failed to open registry store at %s: %w", hivePath, err) + } + + for _, change := range regChanges { + var changeKey winapi.ORHKey + if err = winapi.ORCreateKey(storeHandle, change.keyPath, 0, 0, 0, &changeKey, nil); err != nil { + return fmt.Errorf("failed to open reg key %s: %w", change.keyPath, err) + } + + if err = winapi.ORSetValue(changeKey, change.valueName, uint32(change.valueType), change.data, change.dataLen); err != nil { + return fmt.Errorf("failed to set value for regkey %s\\%s : %w", change.keyPath, change.valueName, err) + } + } + + // remove the existing file first + if err := os.Remove(hivePath); err != nil { + return fmt.Errorf("failed to remove existing registry %s: %w", hivePath, err) + } + + if err = winapi.ORSaveHive(winapi.ORHKey(storeHandle), hivePath, uint32(osversion.Get().MajorVersion), uint32(osversion.Get().MinorVersion)); err != nil { + return fmt.Errorf("error saving the registry store: %w", err) + } + + // close hive irrespective of the errors + if err := winapi.ORCloseHive(winapi.ORHKey(storeHandle)); err != nil { + return fmt.Errorf("error closing registry store; %w", err) + } + return nil + +} + +// mergeHive merges the hive located at parentHivePath with the hive located at deltaHivePath and stores +// the result into the file at mergedHivePath. If a file already exists at path `mergedHivePath` then it +// throws an error. +func mergeHive(parentHivePath, deltaHivePath, mergedHivePath string) (err error) { + var baseHive, deltaHive, mergedHive winapi.ORHKey + if err := winapi.OROpenHive(parentHivePath, &baseHive); err != nil { + return fmt.Errorf("failed to open base hive %s: %w", parentHivePath, err) + } + defer func() { + err2 := winapi.ORCloseHive(baseHive) + if err == nil { + err = errors.Wrap(err2, "failed to close base hive") + } + }() + if err := winapi.OROpenHive(deltaHivePath, &deltaHive); err != nil { + return fmt.Errorf("failed to open delta hive %s: %w", deltaHivePath, err) + } + defer func() { + err2 := winapi.ORCloseHive(deltaHive) + if err == nil { + err = errors.Wrap(err2, "failed to close delta hive") + } + }() + if err := winapi.ORMergeHives([]winapi.ORHKey{baseHive, deltaHive}, &mergedHive); err != nil { + return fmt.Errorf("failed to merge hives: %w", err) + } + defer func() { + err2 := winapi.ORCloseHive(mergedHive) + if err == nil { + err = errors.Wrap(err2, "failed to close merged hive") + } + }() + if err := winapi.ORSaveHive(mergedHive, mergedHivePath, uint32(osversion.Get().MajorVersion), uint32(osversion.Get().MinorVersion)); err != nil { + return fmt.Errorf("failed to save hive: %w", err) + } + return +} + +// getOsBuildNumberFromRegistry fetches the "CurrentBuild" value at path +// "Microsoft\Windows NT\CurrentVersion" from the SOFTWARE registry hive at path +// `regHivePath`. This is used to detect the build version of the uvm. +func getOsBuildNumberFromRegistry(regHivePath string) (_ string, err error) { + var storeHandle, keyHandle winapi.ORHKey + var dataType, dataLen uint32 + keyPath := "Microsoft\\Windows NT\\CurrentVersion" + valueName := "CurrentBuild" + dataLen = 16 // build version string can't be more than 5 wide chars? + dataBuf := make([]byte, dataLen) + + if err = winapi.OROpenHive(regHivePath, &storeHandle); err != nil { + return "", fmt.Errorf("failed to open registry store at %s: %w", regHivePath, err) + } + defer func() { + if closeErr := winapi.ORCloseHive(storeHandle); closeErr != nil { + log.L.WithFields(logrus.Fields{ + "error": closeErr, + "hive": regHivePath, + }).Warnf("failed to close hive") + } + }() + + if err = winapi.OROpenKey(storeHandle, keyPath, &keyHandle); err != nil { + return "", fmt.Errorf("failed to open key at %s: %w", keyPath, err) + } + defer func() { + if closeErr := winapi.ORCloseKey(keyHandle); closeErr != nil { + log.L.WithFields(logrus.Fields{ + "error": closeErr, + "hive": regHivePath, + "key": keyPath, + "value": valueName, + }).Warnf("failed to close hive key") + } + }() + + if err = winapi.ORGetValue(keyHandle, "", valueName, &dataType, &dataBuf[0], &dataLen); err != nil { + return "", fmt.Errorf("failed to get value of %s: %w", valueName, err) + } + + if dataType != uint32(winapi.REG_TYPE_SZ) { + return "", fmt.Errorf("unexpected build number data type (%d)", dataType) + } + + return winapi.ParseUtf16LE(dataBuf[:(dataLen - 2)]), nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/cim_writer_windows.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/cim_writer_windows.go new file mode 100644 index 0000000000..8e88216bfc --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/cim_writer_windows.go @@ -0,0 +1,291 @@ +//go:build windows +// +build windows + +package cimfs + +import ( + "context" + "fmt" + "os" + "path/filepath" + "strings" + "unsafe" + + "github.com/Microsoft/go-winio" + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/winapi" + "github.com/sirupsen/logrus" + "golang.org/x/sys/windows" +) + +// CimFsWriter represents a writer to a single CimFS filesystem instance. On disk, the +// image is composed of a filesystem file and several object ID and region files. +// Note: The CimFsWriter isn't thread safe! +type CimFsWriter struct { + // name of this cim. Usually a .cim file will be created to represent this cim. + name string + // handle is the CIMFS_IMAGE_HANDLE that must be passed when calling CIMFS APIs. + handle winapi.FsHandle + // name of the active file i.e the file to which we are currently writing. + activeName string + // stream to currently active file. + activeStream winapi.StreamHandle + // amount of bytes that can be written to the activeStream. + activeLeft uint64 +} + +// Create creates a new cim image. The CimFsWriter returned can then be used to do +// operations on this cim. +func Create(imagePath string, oldFSName string, newFSName string) (_ *CimFsWriter, err error) { + var oldNameBytes *uint16 + // CimCreateImage API call has different behavior if the value of oldNameBytes / newNameBytes + // is empty than if it is nil. So we have to convert those strings into *uint16 here. + fsName := oldFSName + if oldFSName != "" { + oldNameBytes, err = windows.UTF16PtrFromString(oldFSName) + if err != nil { + return nil, err + } + } + var newNameBytes *uint16 + if newFSName != "" { + fsName = newFSName + newNameBytes, err = windows.UTF16PtrFromString(newFSName) + if err != nil { + return nil, err + } + } + var handle winapi.FsHandle + if err := winapi.CimCreateImage(imagePath, oldNameBytes, newNameBytes, &handle); err != nil { + return nil, fmt.Errorf("failed to create cim image at path %s, oldName: %s, newName: %s: %w", imagePath, oldFSName, newFSName, err) + } + return &CimFsWriter{handle: handle, name: filepath.Join(imagePath, fsName)}, nil +} + +// CreateAlternateStream creates alternate stream of given size at the given path inside the cim. This will +// replace the current active stream. Always, finish writing current active stream and then create an +// alternate stream. +func (c *CimFsWriter) CreateAlternateStream(path string, size uint64) (err error) { + err = c.closeStream() + if err != nil { + return err + } + err = winapi.CimCreateAlternateStream(c.handle, path, size, &c.activeStream) + if err != nil { + return fmt.Errorf("failed to create alternate stream for path %s: %w", path, err) + } + c.activeName = path + return nil +} + +// closes the currently active stream. +func (c *CimFsWriter) closeStream() error { + if c.activeStream == 0 { + return nil + } + err := winapi.CimCloseStream(c.activeStream) + if err == nil && c.activeLeft > 0 { + // Validate here because CimCloseStream does not and this improves error + // reporting. Otherwise the error will occur in the context of + // cimWriteStream. + err = fmt.Errorf("incomplete write, %d bytes left in the stream %s", c.activeLeft, c.activeName) + } + if err != nil { + err = &PathError{Cim: c.name, Op: "closeStream", Path: c.activeName, Err: err} + } + c.activeLeft = 0 + c.activeStream = 0 + c.activeName = "" + return err +} + +// AddFile adds a new file to the image. The file is added at the specified path. After +// calling this function, the file is set as the active stream for the image, so data can +// be written by calling `Write`. +func (c *CimFsWriter) AddFile(path string, info *winio.FileBasicInfo, fileSize int64, securityDescriptor []byte, extendedAttributes []byte, reparseData []byte) error { + err := c.closeStream() + if err != nil { + return err + } + fileMetadata := &winapi.CimFsFileMetadata{ + Attributes: info.FileAttributes, + FileSize: fileSize, + CreationTime: info.CreationTime, + LastWriteTime: info.LastWriteTime, + ChangeTime: info.ChangeTime, + LastAccessTime: info.LastAccessTime, + } + if len(securityDescriptor) == 0 { + // Passing an empty security descriptor creates a CIM in a weird state. + // Pass the NULL DACL. + securityDescriptor = nullSd + } + fileMetadata.SecurityDescriptorBuffer = unsafe.Pointer(&securityDescriptor[0]) + fileMetadata.SecurityDescriptorSize = uint32(len(securityDescriptor)) + if len(reparseData) > 0 { + fileMetadata.ReparseDataBuffer = unsafe.Pointer(&reparseData[0]) + fileMetadata.ReparseDataSize = uint32(len(reparseData)) + } + if len(extendedAttributes) > 0 { + fileMetadata.ExtendedAttributes = unsafe.Pointer(&extendedAttributes[0]) + fileMetadata.EACount = uint32(len(extendedAttributes)) + } + // remove the trailing `\` if present, otherwise it trips off the cim writer + path = strings.TrimSuffix(path, "\\") + err = winapi.CimCreateFile(c.handle, path, fileMetadata, &c.activeStream) + if err != nil { + return &PathError{Cim: c.name, Op: "addFile", Path: path, Err: err} + } + c.activeName = path + if info.FileAttributes&(windows.FILE_ATTRIBUTE_DIRECTORY) == 0 { + c.activeLeft = uint64(fileSize) + } + return nil +} + +// Write writes bytes to the active stream. +func (c *CimFsWriter) Write(p []byte) (int, error) { + if c.activeStream == 0 { + return 0, fmt.Errorf("no active stream") + } + if uint64(len(p)) > c.activeLeft { + return 0, &PathError{Cim: c.name, Op: "write", Path: c.activeName, Err: fmt.Errorf("wrote too much")} + } + err := winapi.CimWriteStream(c.activeStream, uintptr(unsafe.Pointer(&p[0])), uint32(len(p))) + if err != nil { + err = &PathError{Cim: c.name, Op: "write", Path: c.activeName, Err: err} + return 0, err + } + c.activeLeft -= uint64(len(p)) + return len(p), nil +} + +// AddLink adds a hard link from `oldPath` to `newPath` in the image. +func (c *CimFsWriter) AddLink(oldPath string, newPath string) error { + err := c.closeStream() + if err != nil { + return err + } + err = winapi.CimCreateHardLink(c.handle, newPath, oldPath) + if err != nil { + err = &LinkError{Cim: c.name, Op: "addLink", Old: oldPath, New: newPath, Err: err} + } + return err +} + +// Unlink deletes the file at `path` from the image. +func (c *CimFsWriter) Unlink(path string) error { + err := c.closeStream() + if err != nil { + return err + } + //TODO(ambarve): CimDeletePath currently returns an error if the file isn't found but we ideally want + // to put a tombstone at that path so that when cims are merged it removes that file from the lower + // layer + err = winapi.CimDeletePath(c.handle, path) + if err != nil && !os.IsNotExist(err) { + err = &PathError{Cim: c.name, Op: "unlink", Path: path, Err: err} + return err + } + return nil +} + +func (c *CimFsWriter) commit() error { + err := c.closeStream() + if err != nil { + return err + } + err = winapi.CimCommitImage(c.handle) + if err != nil { + err = &OpError{Cim: c.name, Op: "commit", Err: err} + } + return err +} + +// Close closes the CimFS filesystem. +func (c *CimFsWriter) Close() error { + if c.handle == 0 { + return fmt.Errorf("invalid writer") + } + if err := c.commit(); err != nil { + return &OpError{Cim: c.name, Op: "commit", Err: err} + } + if err := winapi.CimCloseImage(c.handle); err != nil { + return &OpError{Cim: c.name, Op: "close", Err: err} + } + c.handle = 0 + return nil +} + +// DestroyCim finds out the region files, object files of this cim and then delete +// the region files, object files and the .cim file itself. +func DestroyCim(ctx context.Context, cimPath string) (retErr error) { + regionFilePaths, err := getRegionFilePaths(ctx, cimPath) + if err != nil { + log.G(ctx).WithError(err).Warnf("get region files for cim %s", cimPath) + if retErr == nil { //nolint:govet // nilness: consistency with below + retErr = err + } + } + objectFilePaths, err := getObjectIDFilePaths(ctx, cimPath) + if err != nil { + log.G(ctx).WithError(err).Warnf("get objectid file for cim %s", cimPath) + if retErr == nil { + retErr = err + } + } + + log.G(ctx).WithFields(logrus.Fields{ + "cimPath": cimPath, + "regionFiles": regionFilePaths, + "objectFiles": objectFilePaths, + }).Debug("destroy cim") + + for _, regFilePath := range regionFilePaths { + if err := os.Remove(regFilePath); err != nil { + log.G(ctx).WithError(err).Warnf("remove file %s", regFilePath) + if retErr == nil { + retErr = err + } + } + } + + for _, objFilePath := range objectFilePaths { + if err := os.Remove(objFilePath); err != nil { + log.G(ctx).WithError(err).Warnf("remove file %s", objFilePath) + if retErr == nil { + retErr = err + } + } + } + + if err := os.Remove(cimPath); err != nil { + log.G(ctx).WithError(err).Warnf("remove file %s", cimPath) + if retErr == nil { + retErr = err + } + } + return retErr +} + +// GetCimUsage returns the total disk usage in bytes by the cim at path `cimPath`. +func GetCimUsage(ctx context.Context, cimPath string) (uint64, error) { + regionFilePaths, err := getRegionFilePaths(ctx, cimPath) + if err != nil { + return 0, fmt.Errorf("get region file paths for cim %s: %w", cimPath, err) + } + objectFilePaths, err := getObjectIDFilePaths(ctx, cimPath) + if err != nil { + return 0, fmt.Errorf("get objectid file for cim %s: %w", cimPath, err) + } + + var totalUsage uint64 + for _, f := range append(regionFilePaths, objectFilePaths...) { + fi, err := os.Stat(f) + if err != nil { + return 0, fmt.Errorf("stat file %s: %w", f, err) + } + totalUsage += uint64(fi.Size()) + } + return totalUsage, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/cimfs.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/cimfs.go new file mode 100644 index 0000000000..21cdf109bc --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/cimfs.go @@ -0,0 +1,17 @@ +//go:build windows +// +build windows + +package cimfs + +import ( + "github.com/Microsoft/hcsshim/osversion" + "github.com/sirupsen/logrus" +) + +func IsCimFSSupported() bool { + rv, err := osversion.BuildRevision() + if err != nil { + logrus.WithError(err).Warn("get build revision") + } + return osversion.Build() == 20348 && rv >= 2031 +} diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/common.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/common.go new file mode 100644 index 0000000000..0a05f5a9d2 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/common.go @@ -0,0 +1,134 @@ +//go:build windows +// +build windows + +package cimfs + +import ( + "bytes" + "context" + "encoding/binary" + "fmt" + "os" + "path/filepath" + + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/pkg/cimfs/format" +) + +var ( + // Equivalent to SDDL of "D:NO_ACCESS_CONTROL". + nullSd = []byte{1, 0, 4, 128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} +) + +type OpError struct { + Cim string + Op string + Err error +} + +func (e *OpError) Error() string { + s := "cim " + e.Op + " " + e.Cim + s += ": " + e.Err.Error() + return s +} + +// PathError is the error type returned by most functions in this package. +type PathError struct { + Cim string + Op string + Path string + Err error +} + +func (e *PathError) Error() string { + s := "cim " + e.Op + " " + e.Cim + s += ":" + e.Path + s += ": " + e.Err.Error() + return s +} + +type LinkError struct { + Cim string + Op string + Old string + New string + Err error +} + +func (e *LinkError) Error() string { + return "cim " + e.Op + " " + e.Old + " " + e.New + ": " + e.Err.Error() +} + +func validateHeader(h *format.CommonHeader) error { + if !bytes.Equal(h.Magic[:], format.MagicValue[:]) { + return fmt.Errorf("not a cim file") + } + if h.Version.Major > format.CurrentVersion.Major || h.Version.Major < format.MinSupportedVersion.Major { + return fmt.Errorf("unsupported cim version. cim version %v must be between %v & %v", h.Version, format.MinSupportedVersion, format.CurrentVersion) + } + return nil +} + +func readFilesystemHeader(f *os.File) (format.FilesystemHeader, error) { + var fsh format.FilesystemHeader + + if err := binary.Read(f, binary.LittleEndian, &fsh); err != nil { + return fsh, fmt.Errorf("reading filesystem header: %w", err) + } + + if err := validateHeader(&fsh.Common); err != nil { + return fsh, fmt.Errorf("validating filesystem header: %w", err) + } + return fsh, nil +} + +// Returns the paths of all the objectID files associated with the cim at `cimPath`. +func getObjectIDFilePaths(ctx context.Context, cimPath string) ([]string, error) { + f, err := os.Open(cimPath) + if err != nil { + return []string{}, fmt.Errorf("open cim file %s: %w", cimPath, err) + } + defer f.Close() + + fsh, err := readFilesystemHeader(f) + if err != nil { + return []string{}, fmt.Errorf("readingp cim header: %w", err) + } + + paths := []string{} + for i := 0; i < int(fsh.Regions.Count); i++ { + path := filepath.Join(filepath.Dir(cimPath), fmt.Sprintf("%s_%v_%d", format.ObjectIDFileName, fsh.Regions.ID, i)) + if _, err := os.Stat(path); err == nil { + paths = append(paths, path) + } else { + log.G(ctx).WithError(err).Warnf("stat for object file %s", path) + } + + } + return paths, nil +} + +// Returns the paths of all the region files associated with the cim at `cimPath`. +func getRegionFilePaths(ctx context.Context, cimPath string) ([]string, error) { + f, err := os.Open(cimPath) + if err != nil { + return []string{}, fmt.Errorf("open cim file %s: %w", cimPath, err) + } + defer f.Close() + + fsh, err := readFilesystemHeader(f) + if err != nil { + return []string{}, fmt.Errorf("reading cim header: %w", err) + } + + paths := []string{} + for i := 0; i < int(fsh.Regions.Count); i++ { + path := filepath.Join(filepath.Dir(cimPath), fmt.Sprintf("%s_%v_%d", format.RegionFileName, fsh.Regions.ID, i)) + if _, err := os.Stat(path); err == nil { + paths = append(paths, path) + } else { + log.G(ctx).WithError(err).Warnf("stat for region file %s", path) + } + } + return paths, nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/doc.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/doc.go new file mode 100644 index 0000000000..9b5476cb6c --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/doc.go @@ -0,0 +1,3 @@ +// This package provides simple go wrappers on top of the win32 CIMFS mount APIs. +// The mounting/unmount of cim layers is done by the cim mount functions the internal/wclayer/cim package. +package cimfs diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/format/doc.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/format/doc.go new file mode 100644 index 0000000000..a85e64710e --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/format/doc.go @@ -0,0 +1,4 @@ +// format package maintains some basic structures to allows us to read header of a cim file. This is mostly +// required to understand the region & objectid files associated with a particular cim. Otherwise, we don't +// need to parse the cim format. +package format diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/format/format.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/format/format.go new file mode 100644 index 0000000000..72dea683eb --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/format/format.go @@ -0,0 +1,61 @@ +//go:build windows +// +build windows + +package format + +import "github.com/Microsoft/go-winio/pkg/guid" + +const ( + RegionFileName = "region" + ObjectIDFileName = "objectid" +) + +// Magic specifies the magic number at the beginning of a file. +type Magic [8]uint8 + +var MagicValue = Magic([8]uint8{'c', 'i', 'm', 'f', 'i', 'l', 'e', '0'}) + +type Version struct { + Major, Minor uint32 +} + +var CurrentVersion = Version{3, 0} + +var MinSupportedVersion = Version{2, 0} + +type FileType uint8 + +// RegionOffset encodes an offset to objects as index of the region file +// containing the object and the byte offset within that file. +type RegionOffset uint64 + +// CommonHeader is the common header for all CIM-related files. +type CommonHeader struct { + Magic Magic + HeaderLength uint32 + Type FileType + Reserved uint8 + Reserved2 uint16 + Version Version + Reserved3 uint64 +} + +type RegionSet struct { + ID guid.GUID + Count uint16 + Reserved uint16 + Reserved1 uint32 +} + +// FilesystemHeader is the header for a filesystem file. +// +// The filesystem file points to the filesystem object inside a region +// file and specifies regions sets. +type FilesystemHeader struct { + Common CommonHeader + Regions RegionSet + FilesystemOffset RegionOffset + Reserved uint32 + Reserved1 uint16 + ParentCount uint16 +} diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/mount_cim.go b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/mount_cim.go new file mode 100644 index 0000000000..ea7341b2f0 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/cimfs/mount_cim.go @@ -0,0 +1,65 @@ +//go:build windows +// +build windows + +package cimfs + +import ( + "fmt" + "path/filepath" + "strings" + + "github.com/Microsoft/go-winio/pkg/guid" + "github.com/Microsoft/hcsshim/internal/winapi" + "github.com/pkg/errors" +) + +type MountError struct { + Cim string + Op string + VolumeGUID guid.GUID + Err error +} + +func (e *MountError) Error() string { + s := "cim " + e.Op + if e.Cim != "" { + s += " " + e.Cim + } + s += " " + e.VolumeGUID.String() + ": " + e.Err.Error() + return s +} + +// Mount mounts the given cim at a volume with given GUID. Returns the full volume +// path if mount is successful. +func Mount(cimPath string, volumeGUID guid.GUID, mountFlags uint32) (string, error) { + if err := winapi.CimMountImage(filepath.Dir(cimPath), filepath.Base(cimPath), mountFlags, &volumeGUID); err != nil { + return "", &MountError{Cim: cimPath, Op: "Mount", VolumeGUID: volumeGUID, Err: err} + } + return fmt.Sprintf("\\\\?\\Volume{%s}\\", volumeGUID.String()), nil +} + +// Unmount unmounts the cim at mounted at path `volumePath`. +func Unmount(volumePath string) error { + // The path is expected to be in the \\?\Volume{GUID}\ format + if volumePath[len(volumePath)-1] != '\\' { + volumePath += "\\" + } + + if !(strings.HasPrefix(volumePath, "\\\\?\\Volume{") && strings.HasSuffix(volumePath, "}\\")) { + return errors.Errorf("volume path %s is not in the expected format", volumePath) + } + + trimmedStr := strings.TrimPrefix(volumePath, "\\\\?\\Volume{") + trimmedStr = strings.TrimSuffix(trimmedStr, "}\\") + + volGUID, err := guid.FromString(trimmedStr) + if err != nil { + return errors.Wrapf(err, "guid parsing failed for %s", trimmedStr) + } + + if err := winapi.CimDismountImage(&volGUID); err != nil { + return &MountError{VolumeGUID: volGUID, Op: "Unmount", Err: err} + } + + return nil +} diff --git a/vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/cim/import.go b/vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/cim/import.go new file mode 100644 index 0000000000..a2e8759529 --- /dev/null +++ b/vendor/github.com/Microsoft/hcsshim/pkg/ociwclayer/cim/import.go @@ -0,0 +1,166 @@ +//go:build windows +// +build windows + +package cim + +import ( + "archive/tar" + "bufio" + "context" + "errors" + "fmt" + "io" + "os" + "path" + "path/filepath" + "strings" + + "github.com/Microsoft/go-winio/backuptar" + "github.com/Microsoft/hcsshim/internal/log" + "github.com/Microsoft/hcsshim/internal/wclayer/cim" + "github.com/Microsoft/hcsshim/pkg/ociwclayer" + "golang.org/x/sys/windows" +) + +// ImportCimLayerFromTar reads a layer from an OCI layer tar stream and extracts it into +// the CIM format at the specified path. The caller must specify the parent layers, if +// any, ordered from lowest to highest layer. +// This function expects that the layer paths (both the layer that is being imported & the parent layers) are +// formatted like `.../snapshots/` and the corresponding layer CIMs are located/will be created at +// `.../snapshots/cim-layers/.cim`. Each CIM file also has corresponding region & objectID files and those +// files will also be stored inside the `cim-layers` directory. +// +// This function returns the total size of the layer's files, in bytes. +func ImportCimLayerFromTar(ctx context.Context, r io.Reader, layerPath string, parentLayerPaths []string) (int64, error) { + err := os.MkdirAll(layerPath, 0) + if err != nil { + return 0, err + } + + w, err := cim.NewCimLayerWriter(ctx, layerPath, parentLayerPaths) + if err != nil { + return 0, err + } + + n, err := writeCimLayerFromTar(ctx, r, w, layerPath) + cerr := w.Close(ctx) + if err != nil { + return 0, err + } + if cerr != nil { + return 0, cerr + } + return n, nil +} + +func writeCimLayerFromTar(ctx context.Context, r io.Reader, w *cim.CimLayerWriter, layerPath string) (int64, error) { + tr := tar.NewReader(r) + buf := bufio.NewWriter(w) + size := int64(0) + + // Iterate through the files in the archive. + hdr, loopErr := tr.Next() + for loopErr == nil { + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + + // Note: path is used instead of filepath to prevent OS specific handling + // of the tar path + base := path.Base(hdr.Name) + if strings.HasPrefix(base, ociwclayer.WhiteoutPrefix) { + name := path.Join(path.Dir(hdr.Name), base[len(ociwclayer.WhiteoutPrefix):]) + if rErr := w.Remove(filepath.FromSlash(name)); rErr != nil { + return 0, rErr + } + hdr, loopErr = tr.Next() + } else if hdr.Typeflag == tar.TypeLink { + if linkErr := w.AddLink(filepath.FromSlash(hdr.Name), filepath.FromSlash(hdr.Linkname)); linkErr != nil { + return 0, linkErr + } + hdr, loopErr = tr.Next() + } else { + name, fileSize, fileInfo, err := backuptar.FileInfoFromHeader(hdr) + if err != nil { + return 0, err + } + sddl, err := backuptar.SecurityDescriptorFromTarHeader(hdr) + if err != nil { + return 0, err + } + eadata, err := backuptar.ExtendedAttributesFromTarHeader(hdr) + if err != nil { + return 0, err + } + + var reparse []byte + // As of now the only valid reparse data in a layer will be for a symlink. If file is + // a symlink set reparse attribute and ensure reparse data buffer isn't + // empty. Otherwise remove the reparse attributed. + fileInfo.FileAttributes &^= uint32(windows.FILE_ATTRIBUTE_REPARSE_POINT) + if hdr.Typeflag == tar.TypeSymlink { + reparse = backuptar.EncodeReparsePointFromTarHeader(hdr) + if len(reparse) > 0 { + fileInfo.FileAttributes |= uint32(windows.FILE_ATTRIBUTE_REPARSE_POINT) + } + } + + if addErr := w.Add(filepath.FromSlash(name), fileInfo, fileSize, sddl, eadata, reparse); addErr != nil { + return 0, addErr + } + if hdr.Typeflag == tar.TypeReg { + if _, cpErr := io.Copy(buf, tr); cpErr != nil { + return 0, cpErr + } + } + size += fileSize + + // Copy all the alternate data streams and return the next non-ADS header. + var ahdr *tar.Header + for { + ahdr, loopErr = tr.Next() + if loopErr != nil { + break + } + + if ahdr.Typeflag != tar.TypeReg || !strings.HasPrefix(ahdr.Name, hdr.Name+":") { + hdr = ahdr + break + } + + // stream names have following format: '::$DATA' + // $DATA is one of the valid types of streams. We currently only support + // data streams so fail if this is some other type of stream. + if !strings.HasSuffix(ahdr.Name, ":$DATA") { + return 0, fmt.Errorf("stream types other than $DATA are not supported, found: %s", ahdr.Name) + } + + if addErr := w.AddAlternateStream(filepath.FromSlash(ahdr.Name), uint64(ahdr.Size)); addErr != nil { + return 0, addErr + } + + if _, cpErr := io.Copy(buf, tr); cpErr != nil { + return 0, cpErr + } + } + } + + if flushErr := buf.Flush(); flushErr != nil { + if loopErr == nil { + loopErr = flushErr + } else { + log.G(ctx).WithError(flushErr).Warn("flush buffer during layer write failed") + } + } + } + if !errors.Is(loopErr, io.EOF) { + return 0, loopErr + } + return size, nil +} + +func DestroyCimLayer(layerPath string) error { + return cim.DestroyCimLayer(context.Background(), layerPath) +} diff --git a/vendor/github.com/containerd/containerd/.gitattributes b/vendor/github.com/containerd/containerd/.gitattributes deleted file mode 100644 index a0717e4b3b..0000000000 --- a/vendor/github.com/containerd/containerd/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -*.go text eol=lf \ No newline at end of file diff --git a/vendor/github.com/containerd/containerd/.gitignore b/vendor/github.com/containerd/containerd/.gitignore deleted file mode 100644 index 73ba2c6853..0000000000 --- a/vendor/github.com/containerd/containerd/.gitignore +++ /dev/null @@ -1,10 +0,0 @@ -/bin/ -/man/ -coverage.txt -profile.out -containerd.test -_site/ -releases/*.tar.gz -releases/*.tar.gz.sha256sum -_output/ -.vagrant/ diff --git a/vendor/github.com/containerd/containerd/.golangci.yml b/vendor/github.com/containerd/containerd/.golangci.yml deleted file mode 100644 index f29bece86f..0000000000 --- a/vendor/github.com/containerd/containerd/.golangci.yml +++ /dev/null @@ -1,96 +0,0 @@ -linters: - enable: - - depguard # Checks for imports that shouldn't be used. - - exportloopref # Checks for pointers to enclosing loop variables - - gofmt - - goimports - - gosec - - ineffassign - - misspell - - nolintlint - - revive - - staticcheck - - tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17 - - unconvert - - unused - - vet - - dupword # Checks for duplicate words in the source code - disable: - - errcheck - -issues: - include: - - EXC0002 - max-issues-per-linter: 0 - max-same-issues: 0 - - # Only using / doesn't work due to https://github.com/golangci/golangci-lint/issues/1398. - exclude-rules: - - path: 'cmd[\\/]containerd[\\/]builtins[\\/]' - text: "blank-imports:" - - path: 'contrib[\\/]fuzz[\\/]' - text: "exported: func name will be used as fuzz.Fuzz" - - path: 'archive[\\/]tarheader[\\/]' - # conversion is necessary on Linux, unnecessary on macOS - text: "unnecessary conversion" - - 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" - - # FIXME temporarily suppress deprecation warnings for the logs package. See https://github.com/containerd/containerd/pull/9086 - - text: "SA1019: log\\.(G|L|Fields|Entry|RFC3339NanoFixed|Level|TraceLevel|DebugLevel|InfoLevel|WarnLevel|ErrorLevel|FatalLevel|PanicLevel|SetLevel|GetLevel|OutputFormat|TextFormat|JSONFormat|SetFormat|WithLogger|GetLogger)" - linters: - - staticcheck - - text: "SA1019: logtest\\.WithT" - linters: - - staticcheck - - -linters-settings: - depguard: - rules: - main: - deny: - - pkg: "github.com/containerd/containerd/log" - desc: The containerd log package was migrated to a separate module. Use github.com/containerd/log instead. - - pkg: "github.com/containerd/containerd/platforms" - desc: The containerd platforms package was migrated to a separate module. Use github.com/containerd/platforms instead. - gosec: - # The following issues surfaced when `gosec` linter - # was enabled. They are temporarily excluded to unblock - # the existing workflow, but still to be addressed by - # future works. - excludes: - - G204 - - G305 - - G306 - - G402 - - G404 - - G115 - -run: - timeout: 8m - skip-dirs: - - api - - cluster - - design - - docs - - docs/man - - releases - - reports - - test # e2e scripts diff --git a/vendor/github.com/containerd/containerd/.mailmap b/vendor/github.com/containerd/containerd/.mailmap deleted file mode 100644 index ef5f7ba41c..0000000000 --- a/vendor/github.com/containerd/containerd/.mailmap +++ /dev/null @@ -1,171 +0,0 @@ -Abhinandan Prativadi -Abhinandan Prativadi -Ace-Tang -Adam Korcz -Akhil Mohan -Aditi Sharma -Akihiro Suda -Akihiro Suda -Allen Sun -Alexander Morozov -Antonio Ojea -Antonio Ojea -Amit Krishnan -Andrei Vagin -Andrey Kolomentsev -Arnaud Porterie -Arnaud Porterie -Bob Mader -Boris Popovschi -Bowen Yan -Brent Baude -Cao Zhihao -Cao Zhihao -Carlos Eduardo -chenxiaoyu -Cory Bennett -Cristian Staretu -Cristian Staretu -Daniel Dao -Derek McGowan -Edgar Lee -Eric Ernst -Eric Lin -Eric Ren -Eric Ren -Eric Ren -Fabian Hoffmann -Fabian Hoffmann <35104465+FabHof@users.noreply.github.com> -Fabiano Fidêncio -Fahed Dorgaa -Frank Yang -Fupan Li -Fupan Li -Fupan Li -Furkan Türkal -Georgia Panoutsakopoulou -guodong -Guangming Wang -Haiyan Meng -haoyun -Harry Zhang -Hu Shuai -Hu Shuai -Iceber Gu -Jaana Burcu Dogan -Jess Valarezo -Jess Valarezo -Jian Liao -Jian Liao -Ji'an Liu -Jie Zhang -Jiongchi Yu -John Howard -John Howard -John Howard -John Howard -Junyu Liu -LongtaoZhang -Lorenz Brun -Luc Perkins -James Sturtevant -Jiajun Jiang -Julien Balestra -Jun Lin Chen <1913688+mc256@users.noreply.github.com> -Justin Cormack -Justin Terry -Justin Terry -Kante -Kazuyoshi Kato -Kazuyoshi Kato -Kenfe-Mickaël Laventure -Kevin Kern -Kevin Parsons -Kevin Xu -Kirtana Ashok -Kitt Hsu -Kohei Tokunaga -Krasi Georgiev -Lantao Liu -Lantao Liu -lengrongfu <1275177125@qq.com> -Li Yuxuan -Lifubang -Lu Jingxiao -Maksym Pavlenko <865334+mxpv@users.noreply.github.com> -Maksym Pavlenko -Maksym Pavlenko -Mario Hros -Mario Hros -Mario Macias -Mark Gordon -Marvin Giessing -Mathis Michel -Michael Crosby -Michael Katsoulis -Mike Brown -Mohammad Asif Siddiqui -Nabeel Rana -Ng Yang -Ning Li -ningmingxiao -Nishchay Kumar -Oliver Stenbom -Phil Estes -Phil Estes -Qian Zhang -Reid Li -Robin Winkelewski -Ross Boucher -Ruediger Maass -Rui Cao -Sakeven Jiang -Samuel Karp -Samuel Karp -Seth Pellegrino <30441101+sethp-nr@users.noreply.github.com> -Shaobao Feng -Shengbo Song -Shengjing Zhu -Siddharth Yadav -SiYu Zhao -Stefan Berger -Stefan Berger -Stephen J Day -Stephen J Day -Stephen J Day -Sudeesh John -Su Fei -Su Xiaolin -Takumasa Sakao -Ted Yu -Tõnis Tiigi -Tony Fang -Tony Fang -Wade Lee -Wade Lee -Wade Lee <21621232@zju.edu.cn> -wanglei -wanglei -wangzhan -Wei Fu -Wei Fu -wen chen -Xiaodong Zhang -Xuean Yan -Yang Yang -Yue Zhang -Yuxing Liu -Zechun Chen -zhang he -Zhang Wei -zhangyadong -Zhenguang Zhu -Zhiyu Li -Zhiyu Li <404977848@qq.com> -Zhongming Chang -Zhoulin Xie -Zhoulin Xie <42261994+JoeWrightss@users.noreply.github.com> -zounengren -张潇 -Kazuyoshi Kato -Andrey Epifanov diff --git a/vendor/github.com/containerd/containerd/ADOPTERS.md b/vendor/github.com/containerd/containerd/ADOPTERS.md deleted file mode 100644 index c5e60df7b4..0000000000 --- a/vendor/github.com/containerd/containerd/ADOPTERS.md +++ /dev/null @@ -1,62 +0,0 @@ -## containerd Adopters - -A non-exhaustive list of containerd adopters is provided below. - -**_Docker/Moby engine_** - Containerd began life prior to its CNCF adoption as a lower-layer -runtime manager for `runc` processes below the Docker engine. Continuing today, containerd -has extremely broad production usage as a component of the [Docker engine](https://github.com/docker/docker-ce) -stack. Note that this includes any use of the open source [Moby engine project](https://github.com/moby/moby); -including the Balena project listed below. - -**_[IBM Cloud Kubernetes Service (IKS)](https://www.ibm.com/cloud/container-service)_** - offers containerd as the CRI runtime for v1.11 and higher versions. - -**_[IBM Cloud Private (ICP)](https://www.ibm.com/cloud/private)_** - IBM's on-premises cloud offering has containerd as a "tech preview" CRI runtime for the Kubernetes offered within this product for the past two releases, and plans to fully migrate to containerd in a future release. - -**_[Google Container-Optimized OS (COS)](https://cloud.google.com/container-optimized-os/docs)_** - Container-Optimized OS is a Linux Operating System from Google that is optimized for running containers. COS has used containerd as container runtime when containerd was part of Docker's core container runtime. - -**_[Google Cloud Kubernetes Engine (GKE)](https://cloud.google.com/kubernetes-engine/)_** - containerd has been offered in GKE since version 1.14 and has been the default runtime since version 1.19. It is also the only supported runtime for GKE Autopilot from the launch. [More details](https://cloud.google.com/kubernetes-engine/docs/concepts/using-containerd) - -**_[AWS Fargate](https://aws.amazon.com/fargate)_** - uses containerd + Firecracker (noted below) as the runtime and isolation technology for containers run in the Fargate platform. Fargate is a serverless, container-native compute offering from Amazon Web Services. - -**_[Amazon Elastic Kubernetes Service (EKS)](https://aws.amazon.com/eks/)_** - EKS optionally offers containerd as a CRI runtime starting with Kubernetes version 1.21. In Kubernetes 1.22 the default CRI runtime will be containerd. - -**_[Bottlerocket](https://aws.amazon.com/bottlerocket/)_** - Bottlerocket is a Linux distribution from Amazon Web Services purpose-built for containers using containerd as the core system runtime. - -**_Cloud Foundry_** - The [Guardian container manager](https://github.com/cloudfoundry/guardian) for CF has been using OCI runC directly with additional code from CF managing the container image and filesystem interactions, but have recently migrated to use containerd as a replacement for the extra code they had written around runC. - -**_Alibaba's PouchContainer_** - The Alibaba [PouchContainer](https://github.com/alibaba/pouch) project uses containerd as its runtime for a cloud native offering that has unique isolation and image distribution capabilities. - -**_Rancher's k3s project_** - Rancher Labs [k3s](https://github.com/rancher/k3s) is a lightweight Kubernetes distribution; in their words: "Easy to install, half the memory, all in a binary less than 40mb." k8s uses containerd as the embedded runtime for this popular lightweight Kubernetes variant. - -**_Rancher's Rio project_** - Rancher Labs [Rio](https://github.com/rancher/rio) project uses containerd as the runtime for a combined Kubernetes, Istio, and container "Cloud Native Container Distribution" platform. - -**_Eliot_** - The [Eliot](https://github.com/ernoaapa/eliot) container project for IoT device container management uses containerd as the runtime. - -**_Balena_** - Resin's [Balena](https://github.com/resin-os/balena) container engine, based on moby/moby but for edge, embedded, and IoT use cases, uses the containerd and runc stack in the same way that the Docker engine uses containerd. - -**_LinuxKit_** - the Moby project's [LinuxKit](https://github.com/linuxkit/linuxkit) for building secure, minimal Linux OS images in a container-native model uses containerd as the core runtime for system and service containers. - -**_BuildKit_** - The Moby project's [BuildKit](https://github.com/moby/buildkit) can use either runC or containerd as build execution backends for building container images. BuildKit support has also been built into the Docker engine in recent releases, making BuildKit provide the backend to the `docker build` command. - -**_[Azure Kubernetes Service (AKS)](https://azure.microsoft.com/services/kubernetes-service)_** - Microsoft's managed Kubernetes offering uses containerd for Linux nodes running v1.19 and greater, and Windows nodes running 1.20 and greater. [More Details](https://docs.microsoft.com/azure/aks/cluster-configuration#container-runtime-configuration) - -**_Amazon Firecracker_** - The AWS [Firecracker VMM project](http://firecracker-microvm.io/) has extended containerd with a new snapshotter and v2 shim to allow containerd to drive virtualized container processes via their VMM implementation. More details on their containerd integration are available in [their GitHub project](https://github.com/firecracker-microvm/firecracker-containerd). - -**_Kata Containers_** - The [Kata containers](https://katacontainers.io/) lightweight-virtualized container runtime project integrates with containerd via a custom v2 shim implementation that drives the Kata container runtime. - -**_D2iQ Konvoy_** - D2iQ Inc [Konvoy](https://d2iq.com/products/konvoy) product uses containerd as the container runtime for its Kubernetes distribution. - -**_Inclavare Containers_** - [Inclavare Containers](https://github.com/alibaba/inclavare-containers) is an innovation of container runtime with the novel approach for launching protected containers in hardware-assisted Trusted Execution Environment (TEE) technology, aka Enclave, which can prevent the untrusted entity, such as Cloud Service Provider (CSP), from accessing the sensitive and confidential assets in use. - -**_VMware TKG_** - [Tanzu Kubernetes Grid](https://tanzu.vmware.com/kubernetes-grid) VMware's Multicloud Kubernetes offering uses containerd as the default CRI runtime. - -**_VMware TCE_** - [Tanzu Community Edition](https://github.com/vmware-tanzu/community-edition) VMware's fully-featured, easy to manage, Kubernetes platform for learners and users. It is a freely available, community supported, and open source distribution of VMware Tanzu. It uses containerd as the default CRI runtime. - -**_[Talos Linux](https://www.talos.dev/)_** - Talos Linux is Linux designed for Kubernetes – secure, immutable, and minimal. Talos Linux is using containerd as the core system runtime and CRI implementation. - -**_Deckhouse_** - [Deckhouse Kubernetes Platform](https://deckhouse.io/) from Flant allows you to manage Kubernetes clusters anywhere in a fully automatic and uniform fashion. It uses containerd as the default CRI runtime. - -**_Other Projects_** - While the above list provides a cross-section of well known uses of containerd, the simplicity and clear API layer for containerd has inspired many smaller projects around providing simple container management platforms. Several examples of building higher layer functionality on top of the containerd base have come from various containerd community participants: - - Michael Crosby's [boss](https://github.com/crosbymichael/boss) project, - - Evan Hazlett's [stellar](https://github.com/ehazlett/stellar) project, - - Paul Knopf's immutable Linux image builder project: [darch](https://github.com/godarch/darch). diff --git a/vendor/github.com/containerd/containerd/BUILDING.md b/vendor/github.com/containerd/containerd/BUILDING.md deleted file mode 100644 index 20edcb59e5..0000000000 --- a/vendor/github.com/containerd/containerd/BUILDING.md +++ /dev/null @@ -1,297 +0,0 @@ -# Build containerd from source - -This guide is useful if you intend to contribute on containerd. Thanks for your -effort. Every contribution is very appreciated. - -This doc includes: -* [Build requirements](#build-requirements) -* [Build the development environment](#build-the-development-environment) -* [Build containerd](#build-containerd) -* [Via docker container](#via-docker-container) -* [Testing](#testing-containerd) - -## Build requirements - -To build the `containerd` daemon, and the `ctr` simple test client, the following build system dependencies are required: - - -* Go 1.22.x or above -* Protoc 3.x compiler and headers (download at the [Google protobuf releases page](https://github.com/protocolbuffers/protobuf/releases)) -* Btrfs headers and libraries for your distribution. Note that building the btrfs driver can be disabled via the build tag `no_btrfs`, removing this dependency. - -> *Note*: On macOS, you need a third party runtime to run containers on containerd - -## Build the development environment - -First you need to setup your Go development environment. You can follow this -guideline [How to write go code](https://golang.org/doc/code.html) and at the -end you have `go` command in your `PATH`. - -You need `git` to checkout the source code: - -```sh -git clone https://github.com/containerd/containerd -``` - -For proper results, install the `protoc` release into `/usr/local` on your build system. For example, the following commands will download and install the 3.11.4 release for a 64-bit Linux host: - -```sh -wget -c https://github.com/protocolbuffers/protobuf/releases/download/v3.11.4/protoc-3.11.4-linux-x86_64.zip -sudo unzip protoc-3.11.4-linux-x86_64.zip -d /usr/local -``` - -To enable optional [Btrfs](https://en.wikipedia.org/wiki/Btrfs) snapshotter, you should have the headers from the Linux kernel 4.12 or later. -The dependency on the kernel headers only affects users building containerd from source. -Users on older kernels may opt to not compile the btrfs support (see `BUILDTAGS=no_btrfs` below), -or to provide headers from a newer kernel. - -> **Note** -> The dependency on the Linux kernel headers 4.12 was introduced in containerd 1.7.0-beta.4. -> -> containerd 1.6 has different set of dependencies for enabling btrfs. -> containerd 1.6 users should refer to https://github.com/containerd/containerd/blob/release/1.6/BUILDING.md#build-the-development-environment - -At this point you are ready to build `containerd` yourself! - -## Runc - -Runc is the default container runtime used by `containerd` and is required to -run containerd. While it is okay to download a `runc` binary and install that on -the system, sometimes it is necessary to build runc directly when working with -container runtime development. Make sure to follow the guidelines for versioning -in [RUNC.md](/docs/RUNC.md) for the best results. - -> *Note*: Runc only supports Linux - -## Build containerd - -`containerd` uses `make` to create a repeatable build flow. It means that you -can run: - -```sh -cd containerd -make -``` - -This is going to build all the project binaries in the `./bin/` directory. - -You can move them in your global path, `/usr/local/bin` with: - -```sh -sudo make install -``` - -The install prefix can be changed by passing the `PREFIX` variable (defaults -to `/usr/local`). - -Note: if you set one of these vars, set them to the same values on all make stages -(build as well as install). - -If you want to prepend an additional prefix on actual installation (eg. packaging or chroot install), -you can pass it via `DESTDIR` variable: - -```sh -sudo make install DESTDIR=/tmp/install-x973234/ -``` - -The above command installs the `containerd` binary to `/tmp/install-x973234/usr/local/bin/containerd` - -The current `DESTDIR` convention is supported since containerd v1.6. -Older releases was using `DESTDIR` for a different purpose that is similar to `PREFIX`. - - -When making any changes to the gRPC API, you can use the installed `protoc` -compiler to regenerate the API generated code packages with: - -```sh -make generate -``` - -> *Note*: Several build tags are currently available: -> * `no_cri`: A build tag disables building Kubernetes [CRI](http://blog.kubernetes.io/2016/12/container-runtime-interface-cri-in-kubernetes.html) support into containerd. -> See [here](https://github.com/containerd/cri-containerd#build-tags) for build tags of CRI plugin. -> * snapshotters (alphabetical order) -> * `no_aufs`: A build tag disables building the aufs snapshot driver. -> * `no_btrfs`: A build tag disables building the Btrfs snapshot driver. -> * `no_devmapper`: A build tag disables building the device mapper snapshot driver. -> * `no_zfs`: A build tag disables building the ZFS snapshot driver. -> * `no_dynamic_plugins`: A build tag disables dynamic plugins. -> -> For example, adding `BUILDTAGS=no_btrfs` to your environment before calling the **binaries** -> Makefile target will disable the btrfs driver within the containerd Go build. - -Vendoring of external imports uses the [Go Modules](https://golang.org/ref/mod#vendoring). You need -to use `go mod` command to modify the dependencies. After modifition, you should run `go mod tidy` -and `go mod vendor` to ensure the `go.mod`, `go.sum` files and `vendor` directory are up to date. -Changes to these files should become a single commit for a PR which relies on vendored updates. - -Please refer to [RUNC.md](/docs/RUNC.md) for the currently supported version of `runc` that is used by containerd. - -> *Note*: On macOS, the containerd daemon can be built and run natively. However, as stated above, runc only supports linux. - -### Static binaries - -You can build static binaries by providing a few variables to `make`: - -```sh -make STATIC=1 -``` - -> *Note*: -> - static build is discouraged -> - static containerd binary does not support loading shared object plugins (`*.so`) -> - static build binaries are not position-independent - -# Via Docker container - -The following instructions assume you are at the parent directory of containerd source directory. - -## Build containerd in a container - -You can build `containerd` via a Linux-based Docker container. -You can build an image from this `Dockerfile`: - -```dockerfile -FROM golang -``` - -Let's suppose that you built an image called `containerd/build`. From the -containerd source root directory you can run the following command: - -```sh -docker run -it \ - -v ${PWD}/containerd:/go/src/github.com/containerd/containerd \ - -e GOPATH=/go \ - -w /go/src/github.com/containerd/containerd containerd/build sh -``` - -This mounts `containerd` repository - -You are now ready to [build](#build-containerd): - -```sh -make && make install -``` - -## Build containerd and runc in a container - -To have complete core container runtime, you will need both `containerd` and `runc`. It is possible to build both of these via Docker container. - -You can use `git` to checkout `runc`: - -```sh -git clone https://github.com/opencontainers/runc -``` - -We can build an image from this `Dockerfile`: - -```sh -FROM golang - -RUN apt-get update && \ - apt-get install -y libseccomp-dev -``` - -In our Docker container we will build `runc` build, which includes -[seccomp](https://en.wikipedia.org/wiki/seccomp), [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux), -and [AppArmor](https://en.wikipedia.org/wiki/AppArmor) support. Seccomp support -in runc requires `libseccomp-dev` as a dependency (AppArmor and SELinux support -do not require external libraries at build time). Refer to [RUNC.md](docs/RUNC.md) -in the docs directory to for details about building runc, and to learn about -supported versions of `runc` as used by containerd. - -Let's suppose you build an image called `containerd/build` from the above Dockerfile. You can run the following command: - -```sh -docker run -it --privileged \ - -v /var/lib/containerd \ - -v ${PWD}/runc:/go/src/github.com/opencontainers/runc \ - -v ${PWD}/containerd:/go/src/github.com/containerd/containerd \ - -e GOPATH=/go \ - -w /go/src/github.com/containerd/containerd containerd/build sh -``` - -This mounts both `runc` and `containerd` repositories in our Docker container. - -From within our Docker container let's build `containerd`: - -```sh -cd /go/src/github.com/containerd/containerd -make && make install -``` - -These binaries can be found in the `./bin` directory in your host. -`make install` will move the binaries in your `$PATH`. - -Next, let's build `runc`: - -```sh -cd /go/src/github.com/opencontainers/runc -make && make install -``` - -For further details about building runc, refer to [RUNC.md](docs/RUNC.md) in the -docs directory. - -When working with `ctr`, the simple test client we just built, don't forget to start the daemon! - -```sh -containerd --config config.toml -``` - -# Testing containerd - -During the automated CI the unit tests and integration tests are run as part of the PR validation. As a developer you can run these tests locally by using any of the following `Makefile` targets: - - `make test`: run all non-integration tests that do not require `root` privileges - - `make root-test`: run all non-integration tests which require `root` - - `make integration`: run all tests, including integration tests and those which require `root`. `TESTFLAGS_PARALLEL` can be used to control parallelism. For example, `TESTFLAGS_PARALLEL=1 make integration` will lead a non-parallel execution. The default value of `TESTFLAGS_PARALLEL` is **8**. - - `make cri-integration`: [CRI Integration Tests](https://github.com/containerd/containerd/blob/main/docs/cri/testing.md#cri-integration-test) run cri integration tests - -To execute a specific test or set of tests you can use the `go test` capabilities -without using the `Makefile` targets. The following examples show how to specify a test -name and also how to use the flag directly against `go test` to run root-requiring tests. - -```sh -# run the test : -go test -v -run "" . -# enable the root-requiring tests: -go test -v -run . -test.root -``` - -Example output from directly running `go test` to execute the `TestContainerList` test: - -```sh -sudo go test -v -run "TestContainerList" . -test.root -INFO[0000] running tests against containerd revision=f2ae8a020a985a8d9862c9eb5ab66902c2888361 version=v1.0.0-beta.2-49-gf2ae8a0 -=== RUN TestContainerList ---- PASS: TestContainerList (0.00s) -PASS -ok github.com/containerd/containerd 4.778s -``` - -> *Note*: in order to run `sudo go` you need to -> - either keep user PATH environment variable. ex: `sudo "PATH=$PATH" env go test ` -> - or use `go test -exec` ex: `go test -exec sudo -v -run "TestTarWithXattr" ./archive/ -test.root` - -## Additional tools - -### containerd-stress -In addition to `go test`-based testing executed via the `Makefile` targets, the `containerd-stress` tool is available and built with the `all` or `binaries` targets and installed during `make install`. - -With this tool you can stress a running containerd daemon for a specified period of time, selecting a concurrency level to generate stress against the daemon. The following command is an example of having five workers running for two hours against a default containerd gRPC socket address: - -```sh -containerd-stress -c 5 -d 120m -``` - -For more information on this tool's options please run `containerd-stress --help`. - -### bucketbench -[Bucketbench](https://github.com/estesp/bucketbench) is an external tool which can be used to drive load against a container runtime, specifying a particular set of lifecycle operations to run with a specified amount of concurrency. Bucketbench is more focused on generating performance details than simply inducing load against containerd. - -Bucketbench differs from the `containerd-stress` tool in a few ways: - - Bucketbench has support for testing the Docker engine, the `runc` binary, and containerd 0.2.x (via `ctr`) and 1.0 (via the client library) branches. - - Bucketbench is driven via configuration file that allows specifying a list of lifecycle operations to execute. This can be used to generate detailed statistics per-command (e.g. start, stop, pause, delete). - - Bucketbench generates detailed reports and timing data at the end of the configured test run. - -More details on how to install and run `bucketbench` are available at the [GitHub project page](https://github.com/estesp/bucketbench). diff --git a/vendor/github.com/containerd/containerd/Makefile b/vendor/github.com/containerd/containerd/Makefile deleted file mode 100644 index f077ae78f3..0000000000 --- a/vendor/github.com/containerd/containerd/Makefile +++ /dev/null @@ -1,493 +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. - - -# Go command to use for build -GO ?= go -INSTALL ?= install - -# Root directory of the project (absolute path). -ROOTDIR=$(dir $(abspath $(lastword $(MAKEFILE_LIST)))) - -# Base path used to install. -# The files will be installed under `$(DESTDIR)/$(PREFIX)`. -# The convention of `DESTDIR` was changed in containerd v1.6. -PREFIX ?= /usr/local -DATADIR ?= $(PREFIX)/share -MANDIR ?= $(DATADIR)/man - -TEST_IMAGE_LIST ?= - -# Used to populate variables in version package. -VERSION ?= $(shell git describe --match 'v[0-9]*' --dirty='.m' --always) -REVISION=$(shell git rev-parse HEAD)$(shell if ! git diff --no-ext-diff --quiet --exit-code; then echo .m; fi) -PACKAGE=github.com/containerd/containerd -SHIM_CGO_ENABLED ?= 0 - -ifneq "$(strip $(shell command -v $(GO) 2>/dev/null))" "" - GOOS ?= $(shell $(GO) env GOOS) - GOARCH ?= $(shell $(GO) env GOARCH) -else - ifeq ($(GOOS),) - # approximate GOOS for the platform if we don't have Go and GOOS isn't - # set. We leave GOARCH unset, so that may need to be fixed. - ifeq ($(OS),Windows_NT) - GOOS = windows - else - UNAME_S := $(shell uname -s) - ifeq ($(UNAME_S),Linux) - GOOS = linux - endif - ifeq ($(UNAME_S),Darwin) - GOOS = darwin - endif - ifeq ($(UNAME_S),FreeBSD) - GOOS = freebsd - endif - endif - else - GOOS ?= $$GOOS - GOARCH ?= $$GOARCH - endif -endif - -ifndef GODEBUG - EXTRA_LDFLAGS += -s -w - DEBUG_GO_GCFLAGS := - DEBUG_TAGS := -else - DEBUG_GO_GCFLAGS := -gcflags=all="-N -l" - DEBUG_TAGS := static_build -endif - -WHALE = "🇩" -ONI = "👹" - -RELEASE=containerd-$(VERSION:v%=%)-${GOOS}-${GOARCH} -STATICRELEASE=containerd-static-$(VERSION:v%=%)-${GOOS}-${GOARCH} -CRIRELEASE=cri-containerd-$(VERSION:v%=%)-${GOOS}-${GOARCH} -CRICNIRELEASE=cri-containerd-cni-$(VERSION:v%=%)-${GOOS}-${GOARCH} - -PKG=github.com/containerd/containerd - -# Project binaries. -COMMANDS=ctr containerd containerd-stress -MANPAGES=ctr.8 containerd.8 containerd-config.8 containerd-config.toml.5 - -ifdef BUILDTAGS - GO_BUILDTAGS = ${BUILDTAGS} -endif -GO_BUILDTAGS ?= -GO_BUILDTAGS += urfave_cli_no_docs -GO_BUILDTAGS += ${DEBUG_TAGS} -ifneq ($(STATIC),) - GO_BUILDTAGS += osusergo netgo static_build -endif -GO_TAGS=$(if $(GO_BUILDTAGS),-tags "$(strip $(GO_BUILDTAGS))",) - -GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -X $(PKG)/version.Package=$(PACKAGE) $(EXTRA_LDFLAGS) -ifneq ($(STATIC),) - GO_LDFLAGS += -extldflags "-static" -endif -GO_LDFLAGS+=' - -SHIM_GO_LDFLAGS=-ldflags '-X $(PKG)/version.Version=$(VERSION) -X $(PKG)/version.Revision=$(REVISION) -X $(PKG)/version.Package=$(PACKAGE) -extldflags "-static" $(EXTRA_LDFLAGS)' - -# Project packages. -PACKAGES=$(shell $(GO) list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration) -NON_API_PACKAGES=$(shell $(GO) list ${GO_TAGS} ./... | grep -v /vendor/ | grep -v /integration | grep -v "containerd/api") -TEST_REQUIRES_ROOT_PACKAGES=$(filter \ - ${PACKAGES}, \ - $(shell \ - for f in $$(git grep -l testutil.RequiresRoot | grep -v Makefile); do \ - d="$$(dirname $$f)"; \ - [ "$$d" = "." ] && echo "${PKG}" && continue; \ - echo "${PKG}/$$d"; \ - done | sort -u) \ - ) - -ifdef SKIPTESTS - PACKAGES:=$(filter-out ${SKIPTESTS},${PACKAGES}) - TEST_REQUIRES_ROOT_PACKAGES:=$(filter-out ${SKIPTESTS},${TEST_REQUIRES_ROOT_PACKAGES}) -endif - -#Replaces ":" (*nix), ";" (windows) with newline for easy parsing -GOPATHS=$(shell go env GOPATH | tr ":" "\n" | tr ";" "\n") - -TESTFLAGS_RACE= -GO_BUILD_FLAGS= -# See Golang issue re: '-trimpath': https://github.com/golang/go/issues/13809 -GO_GCFLAGS=$(shell \ - set -- ${GOPATHS}; \ - echo "-gcflags=-trimpath=$${1}/src"; \ - ) - -BINARIES=$(addprefix bin/,$(COMMANDS)) - -#include platform specific makefile --include Makefile.$(GOOS) - -# Flags passed to `go test` -TESTFLAGS ?= $(TESTFLAGS_RACE) $(EXTRA_TESTFLAGS) -TESTFLAGS_PARALLEL ?= 8 - -# Use this to replace `go test` with, for instance, `gotestsum` -GOTEST ?= $(GO) test - -OUTPUTDIR = $(join $(ROOTDIR), _output) -CRIDIR=$(OUTPUTDIR)/cri - -.PHONY: clean all AUTHORS build binaries test integration generate protos check-protos coverage ci check help install uninstall vendor release static-release mandir install-man genman install-cri-deps cri-release cri-cni-release cri-integration install-deps bin/cri-integration.test remove-replace clean-vendor -.DEFAULT: default - -# Forcibly set the default goal to all, in case an include above brought in a rule definition. -.DEFAULT_GOAL := all - -all: binaries - -check: proto-fmt ## run all linters - @echo "$(WHALE) $@" - GOGC=75 golangci-lint run - -ci: check binaries check-protos coverage coverage-integration ## to be used by the CI - -AUTHORS: .mailmap .git/HEAD - git log --format='%aN <%aE>' | sort -fu > $@ - -generate: protos - @echo "$(WHALE) $@" - @PATH="${ROOTDIR}/bin:${PATH}" $(GO) generate -x ${PACKAGES} - -protos: bin/protoc-gen-go-fieldpath - @echo "$(WHALE) $@" - @find . -path ./vendor -prune -false -o -name '*.pb.go' | xargs rm - $(eval TMPDIR := $(shell mktemp -d)) - @(PATH="${ROOTDIR}/bin:${PATH}" protobuild --quiet ${NON_API_PACKAGES}) - go-fix-acronym -w -a '(Id|Io|Uuid|Os)$$' $(shell find runtime/ -name '*.pb.go') - -check-protos: protos ## check if protobufs needs to be generated again - @echo "$(WHALE) $@" - @test -z "$$(git status --short | grep ".pb.go" | tee /dev/stderr)" || \ - ((git diff | cat) && \ - (echo "$(ONI) please run 'make protos' when making changes to proto files" && false)) - -check-api-descriptors: protos ## check that protobuf changes aren't present. - @echo "$(WHALE) $@" - @test -z "$$(git status --short | grep ".pb.txt" | tee /dev/stderr)" || \ - ((git diff $$(find . -name '*.pb.txt') | cat) && \ - (echo "$(ONI) please run 'make protos' when making changes to proto files and check-in the generated descriptor file changes" && false)) - -proto-fmt: ## check format of proto files - @echo "$(WHALE) $@" - @test -z "$$(find . -path ./vendor -prune -o -path ./protobuf/google/rpc -prune -o -name '*.proto' -type f -exec grep -Hn -e "^ " {} \; | tee /dev/stderr)" || \ - (echo "$(ONI) please indent proto files with tabs only" && false) - -build: ## build the go packages - @echo "$(WHALE) $@" - @$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} ${EXTRA_FLAGS} ${GO_LDFLAGS} ${PACKAGES} - -test: ## run tests, except integration tests and tests that require root - @echo "$(WHALE) $@" - @$(GOTEST) ${TESTFLAGS} ${PACKAGES} - -root-test: ## run tests, except integration tests - @echo "$(WHALE) $@" - @$(GOTEST) ${TESTFLAGS} ${TEST_REQUIRES_ROOT_PACKAGES} -test.root - -integration: ## run integration tests - @echo "$(WHALE) $@" - @cd "${ROOTDIR}/integration/client" && $(GO) mod download && $(GOTEST) -v ${TESTFLAGS} -test.root -parallel ${TESTFLAGS_PARALLEL} . - -# TODO integrate cri integration bucket with coverage -bin/cri-integration.test: - @echo "$(WHALE) $@" - @$(GO) test -c ./integration -o bin/cri-integration.test - -cri-integration: binaries bin/cri-integration.test ## run cri integration tests (example: FOCUS=TestContainerListStats make cri-integration) - @echo "$(WHALE) $@" - @bash ./script/test/cri-integration.sh - @rm -rf bin/cri-integration.test - -# build runc shimv2 with failpoint control, only used by integration test -bin/containerd-shim-runc-fp-v1: integration/failpoint/cmd/containerd-shim-runc-fp-v1 FORCE - @echo "$(WHALE) $@" - @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./integration/failpoint/cmd/containerd-shim-runc-fp-v1 - -# build CNI bridge plugin wrapper with failpoint support, only used by integration test -bin/cni-bridge-fp: integration/failpoint/cmd/cni-bridge-fp FORCE - @echo "$(WHALE) $@" - @$(GO) build ${GO_BUILD_FLAGS} -o $@ ./integration/failpoint/cmd/cni-bridge-fp - -# build runc-fp as runc wrapper to support failpoint, only used by integration test -bin/runc-fp: integration/failpoint/cmd/runc-fp FORCE - @echo "$(WHALE) $@" - @$(GO) build ${GO_BUILD_FLAGS} -o $@ ./integration/failpoint/cmd/runc-fp - -benchmark: ## run benchmarks tests - @echo "$(WHALE) $@" - @$(GO) test ${TESTFLAGS} -bench . -run Benchmark -test.root - -FORCE: - -define BUILD_BINARY -@echo "$(WHALE) $@" -$(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@ ${GO_LDFLAGS} ${GO_TAGS} ./$< -endef - -# Build a binary from a cmd. -bin/%: cmd/% FORCE - $(call BUILD_BINARY) - -# gen-manpages must not have the urfave_cli_no_docs build-tag set -bin/gen-manpages: cmd/gen-manpages FORCE - @echo "$(WHALE) $@" - $(GO) build ${DEBUG_GO_GCFLAGS} ${GO_GCFLAGS} ${GO_BUILD_FLAGS} -o $@ ${GO_LDFLAGS} $(subst urfave_cli_no_docs,,${GO_TAGS}) ./cmd/gen-manpages - -bin/containerd-shim: cmd/containerd-shim FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 - @echo "$(WHALE) $@" - @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim - -bin/containerd-shim-runc-v1: cmd/containerd-shim-runc-v1 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 - @echo "$(WHALE) $@" - @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v1 - -bin/containerd-shim-runc-v2: cmd/containerd-shim-runc-v2 FORCE # set !cgo and omit pie for a static shim build: https://github.com/golang/go/issues/17789#issuecomment-258542220 - @echo "$(WHALE) $@" - @CGO_ENABLED=${SHIM_CGO_ENABLED} $(GO) build ${GO_BUILD_FLAGS} -o $@ ${SHIM_GO_LDFLAGS} ${GO_TAGS} ./cmd/containerd-shim-runc-v2 - -binaries: $(BINARIES) ## build binaries - @echo "$(WHALE) $@" - -man: mandir $(addprefix man/,$(MANPAGES)) - @echo "$(WHALE) $@" - -mandir: - @mkdir -p man - -# Kept for backwards compatibility -genman: man/containerd.8 man/ctr.8 - -man/containerd.8: bin/gen-manpages FORCE - @echo "$(WHALE) $@" - $< $(@F) $(@D) - -man/ctr.8: bin/gen-manpages FORCE - @echo "$(WHALE) $@" - $< $(@F) $(@D) - -man/%: docs/man/%.md FORCE - @echo "$(WHALE) $@" - go-md2man -in "$<" -out "$@" - -define installmanpage -$(INSTALL) -d $(DESTDIR)$(MANDIR)/man$(2); -gzip -c $(1) >$(DESTDIR)$(MANDIR)/man$(2)/$(3).gz; -endef - -install-man: man - @echo "$(WHALE) $@" - $(foreach manpage,$(addprefix man/,$(MANPAGES)), $(call installmanpage,$(manpage),$(subst .,,$(suffix $(manpage))),$(notdir $(manpage)))) - - -define pack_release - @rm -rf releases/$(1) releases/$(1).tar.gz - @$(INSTALL) -d releases/$(1)/bin - @$(INSTALL) $(BINARIES) releases/$(1)/bin - @tar -czf releases/$(1).tar.gz -C releases/$(1) bin - @rm -rf releases/$(1) -endef - - -releases/$(RELEASE).tar.gz: $(BINARIES) - @echo "$(WHALE) $@" - $(call pack_release,$(RELEASE)) - -release: releases/$(RELEASE).tar.gz - @echo "$(WHALE) $@" - @cd releases && sha256sum $(RELEASE).tar.gz >$(RELEASE).tar.gz.sha256sum - -releases/$(STATICRELEASE).tar.gz: -ifeq ($(GOOS),linux) - @make STATIC=1 $(BINARIES) - @echo "$(WHALE) $@" - $(call pack_release,$(STATICRELEASE)) -else - @echo "Skipping $(STATICRELEASE) for $(GOOS)" -endif - -static-release: releases/$(STATICRELEASE).tar.gz -ifeq ($(GOOS),linux) - @echo "$(WHALE) $@" - @cd releases && sha256sum $(STATICRELEASE).tar.gz >$(STATICRELEASE).tar.gz.sha256sum -else - @echo "Skipping releasing $(STATICRELEASE) for $(GOOS)" -endif - -# install of cri deps into release output directory -ifeq ($(GOOS),windows) -install-cri-deps: $(BINARIES) - $(INSTALL) -d $(CRIDIR) - DESTDIR=$(CRIDIR) script/setup/install-cni-windows - cp bin/* $(CRIDIR) -else -install-cri-deps: $(BINARIES) - @rm -rf ${CRIDIR} - @$(INSTALL) -d ${CRIDIR}/usr/local/bin - @$(INSTALL) -D -m 755 bin/* ${CRIDIR}/usr/local/bin - @$(INSTALL) -d ${CRIDIR}/opt/containerd/cluster - @cp -r contrib/gce ${CRIDIR}/opt/containerd/cluster/ - @$(INSTALL) -d ${CRIDIR}/etc/systemd/system - @$(INSTALL) -m 644 containerd.service ${CRIDIR}/etc/systemd/system - echo "CONTAINERD_VERSION: '$(VERSION:v%=%)'" | tee ${CRIDIR}/opt/containerd/cluster/version - - DESTDIR=$(CRIDIR) script/setup/install-runc - DESTDIR=$(CRIDIR) script/setup/install-cni - DESTDIR=$(CRIDIR) script/setup/install-critools - DESTDIR=$(CRIDIR) script/setup/install-imgcrypt - - @$(INSTALL) -d $(CRIDIR)/bin - @$(INSTALL) $(BINARIES) $(CRIDIR)/bin -endif - -$(CRIDIR)/cri-containerd.DEPRECATED.txt: - @mkdir -p $(CRIDIR) - @$(INSTALL) -m 644 releases/cri-containerd.DEPRECATED.txt $@ - -ifeq ($(GOOS),windows) -releases/$(CRIRELEASE).tar.gz: install-cri-deps $(CRIDIR)/cri-containerd.DEPRECATED.txt - @echo "$(WHALE) $@" - @cd $(CRIDIR) && tar -czf ../../releases/$(CRIRELEASE).tar.gz * - -releases/$(CRICNIRELEASE).tar.gz: install-cri-deps $(CRIDIR)/cri-containerd.DEPRECATED.txt - @echo "$(WHALE) $@" - @cd $(CRIDIR) && tar -czf ../../releases/$(CRICNIRELEASE).tar.gz * -else -releases/$(CRIRELEASE).tar.gz: install-cri-deps $(CRIDIR)/cri-containerd.DEPRECATED.txt - @echo "$(WHALE) $@" - @tar -czf releases/$(CRIRELEASE).tar.gz -C $(CRIDIR) cri-containerd.DEPRECATED.txt etc/crictl.yaml etc/systemd usr opt/containerd - -releases/$(CRICNIRELEASE).tar.gz: install-cri-deps $(CRIDIR)/cri-containerd.DEPRECATED.txt - @echo "$(WHALE) $@" - @tar -czf releases/$(CRICNIRELEASE).tar.gz -C $(CRIDIR) cri-containerd.DEPRECATED.txt etc usr opt -endif - -cri-release: releases/$(CRIRELEASE).tar.gz - @echo "$(WHALE) $@" - @cd releases && sha256sum $(CRIRELEASE).tar.gz >$(CRIRELEASE).tar.gz.sha256sum && ln -sf $(CRIRELEASE).tar.gz cri-containerd.tar.gz - -cri-cni-release: releases/$(CRICNIRELEASE).tar.gz - @echo "$(WHALE) $@" - @cd releases && sha256sum $(CRICNIRELEASE).tar.gz >$(CRICNIRELEASE).tar.gz.sha256sum && ln -sf $(CRICNIRELEASE).tar.gz cri-cni-containerd.tar.gz - -clean: ## clean up binaries - @echo "$(WHALE) $@" - @rm -f $(BINARIES) - @rm -f releases/*.tar.gz* - @rm -rf $(OUTPUTDIR) - @rm -rf bin/cri-integration.test - -clean-test: ## clean up debris from previously failed tests - @echo "$(WHALE) $@" - $(eval containers=$(shell find /run/containerd/runc -mindepth 2 -maxdepth 3 -type d -exec basename {} \;)) - $(shell pidof containerd containerd-shim runc | xargs -r -n 1 kill -9) - @( for container in $(containers); do \ - grep $$container /proc/self/mountinfo | while read -r mountpoint; do \ - umount $$(echo $$mountpoint | awk '{print $$5}'); \ - done; \ - find /sys/fs/cgroup -name $$container -print0 | xargs -r -0 rmdir; \ - done ) - @rm -rf /run/containerd/runc/* - @rm -rf /run/containerd/fifo/* - @rm -rf /run/containerd-test/* - @rm -rf bin/cri-integration.test - @rm -rf bin/cni-bridge-fp - @rm -rf bin/containerd-shim-runc-fp-v1 - -install: ## install binaries - @echo "$(WHALE) $@ $(BINARIES)" - @$(INSTALL) -d $(DESTDIR)$(PREFIX)/bin - @$(INSTALL) $(BINARIES) $(DESTDIR)$(PREFIX)/bin - -uninstall: - @echo "$(WHALE) $@" - @rm -f $(addprefix $(DESTDIR)$(PREFIX)/bin/,$(notdir $(BINARIES))) - -ifeq ($(GOOS),windows) -install-deps: - # TODO: need a script for hcshim something like containerd/cri/hack/install/windows/install-hcsshim.sh - script/setup/install-critools - script/setup/install-cni-windows -else -install-deps: ## install cri dependencies - script/setup/install-seccomp - script/setup/install-runc - script/setup/install-critools - script/setup/install-cni -endif - -coverage: ## generate coverprofiles from the unit tests, except tests that require root - @echo "$(WHALE) $@" - @rm -f coverage.txt - @$(GO) test -i ${TESTFLAGS} ${PACKAGES} 2> /dev/null - @( for pkg in ${PACKAGES}; do \ - $(GO) test ${TESTFLAGS} \ - -cover \ - -coverprofile=profile.out \ - -covermode=atomic $$pkg || exit; \ - if [ -f profile.out ]; then \ - cat profile.out >> coverage.txt; \ - rm profile.out; \ - fi; \ - done ) - -root-coverage: ## generate coverage profiles for unit tests that require root - @echo "$(WHALE) $@" - @$(GO) test -i ${TESTFLAGS} ${TEST_REQUIRES_ROOT_PACKAGES} 2> /dev/null - @( for pkg in ${TEST_REQUIRES_ROOT_PACKAGES}; do \ - $(GO) test ${TESTFLAGS} \ - -cover \ - -coverprofile=profile.out \ - -covermode=atomic $$pkg -test.root || exit; \ - if [ -f profile.out ]; then \ - cat profile.out >> coverage.txt; \ - rm profile.out; \ - fi; \ - done ) - -remove-replace: - @echo "$(WHALE) $@" - @$(GO) mod edit -dropreplace=github.com/containerd/containerd/api - -vendor: ## ensure all the go.mod/go.sum files are up-to-date including vendor/ directory - @echo "$(WHALE) $@" - @$(GO) mod tidy - @$(GO) mod vendor - @$(GO) mod verify - @(cd ${ROOTDIR}/integration/client && ${GO} mod tidy) - -verify-vendor: ## verify if all the go.mod/go.sum files are up-to-date - @echo "$(WHALE) $@" - $(eval TMPDIR := $(shell mktemp -d)) - @cp -R ${ROOTDIR} ${TMPDIR} - @(cd ${TMPDIR}/containerd && ${GO} mod tidy) - @(cd ${TMPDIR}/containerd/integration/client && ${GO} mod tidy) - @diff -r -u -q ${ROOTDIR} ${TMPDIR}/containerd - @rm -rf ${TMPDIR} - @${ROOTDIR}/script/verify-go-modules.sh integration/client - -clean-vendor: remove-replace vendor - - -help: ## this help - @awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z_-]+:.*?## / {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST) | sort diff --git a/vendor/github.com/containerd/containerd/Makefile.darwin b/vendor/github.com/containerd/containerd/Makefile.darwin deleted file mode 100644 index 5303ca40ac..0000000000 --- a/vendor/github.com/containerd/containerd/Makefile.darwin +++ /dev/null @@ -1,22 +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. - - -#darwin specific settings -COMMANDS += containerd-shim - -# amd64 supports go test -race -ifeq ($(GOARCH),amd64) - TESTFLAGS_RACE= -race -endif diff --git a/vendor/github.com/containerd/containerd/Makefile.freebsd b/vendor/github.com/containerd/containerd/Makefile.freebsd deleted file mode 100644 index 78e7f2de45..0000000000 --- a/vendor/github.com/containerd/containerd/Makefile.freebsd +++ /dev/null @@ -1,22 +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. - - -#freebsd specific settings -COMMANDS += containerd-shim - -# amd64 supports go test -race -ifeq ($(GOARCH),amd64) - TESTFLAGS_RACE= -race -endif diff --git a/vendor/github.com/containerd/containerd/Makefile.linux b/vendor/github.com/containerd/containerd/Makefile.linux deleted file mode 100644 index 0541400703..0000000000 --- a/vendor/github.com/containerd/containerd/Makefile.linux +++ /dev/null @@ -1,33 +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. - - -#linux specific settings -WHALE="+" -ONI="-" -COMMANDS += containerd-shim containerd-shim-runc-v1 containerd-shim-runc-v2 - -# check GOOS for cross compile builds -ifeq ($(GOOS),linux) - ifneq ($(GOARCH),$(filter $(GOARCH),mips mipsle mips64 mips64le ppc64)) - ifeq ($(STATIC),) - GO_GCFLAGS += -buildmode=pie - endif - endif -endif - -# amd64 supports go test -race -ifeq ($(GOARCH),amd64) - TESTFLAGS_RACE= -race -endif diff --git a/vendor/github.com/containerd/containerd/Makefile.windows b/vendor/github.com/containerd/containerd/Makefile.windows deleted file mode 100644 index 6e62a87cf8..0000000000 --- a/vendor/github.com/containerd/containerd/Makefile.windows +++ /dev/null @@ -1,32 +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. - - -#Windows specific settings. -WHALE = "+" -ONI = "-" - -# amd64 supports go test -race -ifeq ($(GOARCH),amd64) - TESTFLAGS_RACE= -race -endif - -WINDOWS_SHIM=bin/containerd-shim-runhcs-v1.exe -BINARIES := $(addsuffix .exe,$(BINARIES)) $(WINDOWS_SHIM) - -$(WINDOWS_SHIM): script/setup/install-runhcs-shim go.mod - DESTDIR=$(CURDIR)/bin $< - -bin/%.exe: cmd/% FORCE - $(BUILD_BINARY) diff --git a/vendor/github.com/containerd/containerd/Protobuild.toml b/vendor/github.com/containerd/containerd/Protobuild.toml deleted file mode 100644 index b5ecfb464d..0000000000 --- a/vendor/github.com/containerd/containerd/Protobuild.toml +++ /dev/null @@ -1,37 +0,0 @@ -version = "2" -generators = ["go"] - -# Control protoc include paths. Below are usually some good defaults, but feel -# free to try it without them if it works for your project. -[includes] - # Include paths that will be added before all others. Typically, you want to - # treat the root of the project as an include, but this may not be necessary. - before = ["./protobuf", "./vendor"] - - # Paths that will be added untouched to the end of the includes. We use - # `/usr/local/include` to pickup the common install location of protobuf. - # This is the default. - after = ["/usr/local/include", "/usr/include"] - -[[overrides]] -# enable ttrpc and disable fieldpath and grpc for the shim -prefixes = [ - "github.com/containerd/containerd/runtime/v1/shim/v1", - "github.com/containerd/containerd/api/runtime/task/v2", - "github.com/containerd/containerd/api/runtime/sandbox/v1", -] -generators = ["go", "go-ttrpc"] - -[[overrides]] -prefixes = [ - "github.com/containerd/containerd/third_party/k8s.io/cri-api/pkg/apis/runtime/v1alpha2", -] -generators = ["go", "go-grpc"] - -# Lock down runc config -[[descriptors]] -prefix = "github.com/containerd/containerd/runtime/linux/runctypes" -target = "runtime/linux/runctypes/next.pb.txt" -ignore_files = [ - "google/protobuf/descriptor.proto", -] diff --git a/vendor/github.com/containerd/containerd/README.md b/vendor/github.com/containerd/containerd/README.md deleted file mode 100644 index 25bcaeebea..0000000000 --- a/vendor/github.com/containerd/containerd/README.md +++ /dev/null @@ -1,356 +0,0 @@ -![containerd banner light mode](https://raw.githubusercontent.com/cncf/artwork/master/projects/containerd/horizontal/color/containerd-horizontal-color.png#gh-light-mode-only) -![containerd banner dark mode](https://raw.githubusercontent.com/cncf/artwork/master/projects/containerd/horizontal/white/containerd-horizontal-white.png#gh-dark-mode-only) - -[![PkgGoDev](https://pkg.go.dev/badge/github.com/containerd/containerd)](https://pkg.go.dev/github.com/containerd/containerd) -[![Build Status](https://github.com/containerd/containerd/workflows/CI/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ACI) -[![Nightlies](https://github.com/containerd/containerd/workflows/Nightly/badge.svg)](https://github.com/containerd/containerd/actions?query=workflow%3ANightly) -[![Go Report Card](https://goreportcard.com/badge/github.com/containerd/containerd)](https://goreportcard.com/report/github.com/containerd/containerd) -[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/1271/badge)](https://bestpractices.coreinfrastructure.org/projects/1271) - -containerd is an industry-standard container runtime with an emphasis on simplicity, robustness, and portability. It is available as a daemon for Linux and Windows, which can manage the complete container lifecycle of its host system: image transfer and storage, container execution and supervision, low-level storage and network attachments, etc. - -containerd is a member of CNCF with ['graduated'](https://landscape.cncf.io/?selected=containerd) status. - -containerd is designed to be embedded into a larger system, rather than being used directly by developers or end-users. - -![architecture](docs/historical/design/architecture.png) - -## Announcements - -### Hello Kubernetes v1.24! -The containerd project would like to announce containerd [v1.6.4](https://github.com/containerd/containerd/releases/tag/v1.6.4). While other prior releases are supported, this latest release and the containerd [v1.5.11](https://github.com/containerd/containerd/releases/tag/v1.5.11) release are recommended for Kubernetes v1.24. - -We felt it important to announce this, particularly in view of [the dockershim removal from this release of Kubernetes](https://kubernetes.io/blog/2022/05/03/dockershim-historical-context/). - -It should be noted here that moving to CRI integrations has been in the plan for many years. `containerd` began as part of `Docker` and was donated to `CNCF`. `containerd` remains in use today by Docker/moby/buildkit etc., and has many other [adopters](https://github.com/containerd/containerd/blob/main/ADOPTERS.md). `containerd` has a namespace that isolates use of `containerd` from various clients/adopters. The Kubernetes namespace is appropriately named `k8s.io`. The CRI API and `containerd` CRI plugin project has, from the start, been an effort to reduce the impact surface for Kubernetes container runtime integration. If you can't tell, we are excited to see this come to fruition. - -If you have any concerns or questions, we will be here to answer them in [issues, discussions, and/or on slack](#communication). Below you will find information/detail about our [CRI Integration](#cri) implementation. - -For containerd users already on v1.6.0-v1.6.3, there are known issues addressed by [v1.6.4](https://github.com/containerd/containerd/releases/tag/v1.6.4). The issues are primarily related to [CNI setup](https://github.com/kubernetes/website/blob/dev-1.24/content/en/docs/tasks/administer-cluster/migrating-from-dockershim/troubleshooting-cni-plugin-related-errors.md) - -### Now Recruiting - -We are a large inclusive OSS project that is welcoming help of any kind shape or form: -* Documentation help is needed to make the product easier to consume and extend. -* We need OSS community outreach/organizing help to get the word out; manage -and create messaging and educational content; and help with social media, community forums/groups, and google groups. -* We are actively inviting new [security advisors](https://github.com/containerd/project/blob/main/GOVERNANCE.md#security-advisors) to join the team. -* New subprojects are being created, core and non-core that could use additional development help. -* Each of the [containerd projects](https://github.com/containerd) has a list of issues currently being worked on or that need help resolving. - - If the issue has not already been assigned to someone or has not made recent progress, and you are interested, please inquire. - - If you are interested in starting with a smaller/beginner-level issue, look for issues with an `exp/beginner` tag, for example [containerd/containerd beginner issues.](https://github.com/containerd/containerd/issues?q=is%3Aissue+is%3Aopen+label%3Aexp%2Fbeginner) - -## Getting Started - -See our documentation on [containerd.io](https://containerd.io): -* [for ops and admins](docs/ops.md) -* [namespaces](docs/namespaces.md) -* [client options](docs/client-opts.md) - -See how to build containerd from source at [BUILDING](BUILDING.md). - -If you are interested in trying out containerd see our example at [Getting Started](docs/getting-started.md). - -## Nightly builds - -There are nightly builds available for download [here](https://github.com/containerd/containerd/actions?query=workflow%3ANightly). -Binaries are generated from `main` branch every night for `Linux` and `Windows`. - -Please be aware: nightly builds might have critical bugs, it's not recommended for use in production and no support provided. - -## Runtime Requirements - -Runtime requirements for containerd are very minimal. Most interactions with -the Linux and Windows container feature sets are handled via [runc](https://github.com/opencontainers/runc) and/or -OS-specific libraries (e.g. [hcsshim](https://github.com/Microsoft/hcsshim) for Microsoft). -The current required version of `runc` is described in [RUNC.md](docs/RUNC.md). - -There are specific features -used by containerd core code and snapshotters that will require a minimum kernel -version on Linux. With the understood caveat of distro kernel versioning, a -reasonable starting point for Linux is a minimum 4.x kernel version. - -The overlay filesystem snapshotter, used by default, uses features that were -finalized in the 4.x kernel series. If you choose to use btrfs, there may -be more flexibility in kernel version (minimum recommended is 3.18), but will -require the btrfs kernel module and btrfs tools to be installed on your Linux -distribution. - -To use Linux checkpoint and restore features, you will need `criu` installed on -your system. See more details in [Checkpoint and Restore](#checkpoint-and-restore). - -Build requirements for developers are listed in [BUILDING](BUILDING.md). - - -## Supported Registries - -Any registry which is compliant with the [OCI Distribution Specification](https://github.com/opencontainers/distribution-spec) -is supported by containerd. - -For configuring registries, see [registry host configuration documentation](docs/hosts.md) - -## Features - -### Client - -containerd offers a full client package to help you integrate containerd into your platform. - -```go - -import ( - "context" - - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/namespaces" -) - - -func main() { - client, err := containerd.New("/run/containerd/containerd.sock") - defer client.Close() -} - -``` - -### Namespaces - -Namespaces allow multiple consumers to use the same containerd without conflicting with each other. It has the benefit of sharing content while maintaining separation with containers and images. - -To set a namespace for requests to the API: - -```go -context = context.Background() -// create a context for docker -docker = namespaces.WithNamespace(context, "docker") - -containerd, err := client.NewContainer(docker, "id") -``` - -To set a default namespace on the client: - -```go -client, err := containerd.New(address, containerd.WithDefaultNamespace("docker")) -``` - -### Distribution - -```go -// pull an image -image, err := client.Pull(context, "docker.io/library/redis:latest") - -// push an image -err := client.Push(context, "docker.io/library/redis:latest", image.Target()) -``` - -### Containers - -In containerd, a container is a metadata object. Resources such as an OCI runtime specification, image, root filesystem, and other metadata can be attached to a container. - -```go -redis, err := client.NewContainer(context, "redis-master") -defer redis.Delete(context) -``` - -### OCI Runtime Specification - -containerd fully supports the OCI runtime specification for running containers. We have built-in functions to help you generate runtime specifications based on images as well as custom parameters. - -You can specify options when creating a container about how to modify the specification. - -```go -redis, err := client.NewContainer(context, "redis-master", containerd.WithNewSpec(oci.WithImageConfig(image))) -``` - -### Root Filesystems - -containerd allows you to use overlay or snapshot filesystems with your containers. It comes with built-in support for overlayfs and btrfs. - -```go -// pull an image and unpack it into the configured snapshotter -image, err := client.Pull(context, "docker.io/library/redis:latest", containerd.WithPullUnpack) - -// allocate a new RW root filesystem for a container based on the image -redis, err := client.NewContainer(context, "redis-master", - containerd.WithNewSnapshot("redis-rootfs", image), - containerd.WithNewSpec(oci.WithImageConfig(image)), -) - -// use a readonly filesystem with multiple containers -for i := 0; i < 10; i++ { - id := fmt.Sprintf("id-%s", i) - container, err := client.NewContainer(ctx, id, - containerd.WithNewSnapshotView(id, image), - containerd.WithNewSpec(oci.WithImageConfig(image)), - ) -} -``` - -### Tasks - -Taking a container object and turning it into a runnable process on a system is done by creating a new `Task` from the container. A task represents the runnable object within containerd. - -```go -// create a new task -task, err := redis.NewTask(context, cio.NewCreator(cio.WithStdio)) -defer task.Delete(context) - -// the task is now running and has a pid that can be used to setup networking -// or other runtime settings outside of containerd -pid := task.Pid() - -// start the redis-server process inside the container -err := task.Start(context) - -// wait for the task to exit and get the exit status -status, err := task.Wait(context) -``` - -### Checkpoint and Restore - -If you have [criu](https://criu.org/Main_Page) installed on your machine you can checkpoint and restore containers and their tasks. This allows you to clone and/or live migrate containers to other machines. - -```go -// checkpoint the task then push it to a registry -checkpoint, err := task.Checkpoint(context) - -err := client.Push(context, "myregistry/checkpoints/redis:master", checkpoint) - -// on a new machine pull the checkpoint and restore the redis container -checkpoint, err := client.Pull(context, "myregistry/checkpoints/redis:master") - -redis, err = client.NewContainer(context, "redis-master", containerd.WithNewSnapshot("redis-rootfs", checkpoint)) -defer container.Delete(context) - -task, err = redis.NewTask(context, cio.NewCreator(cio.WithStdio), containerd.WithTaskCheckpoint(checkpoint)) -defer task.Delete(context) - -err := task.Start(context) -``` - -### Snapshot Plugins - -In addition to the built-in Snapshot plugins in containerd, additional external -plugins can be configured using GRPC. An external plugin is made available using -the configured name and appears as a plugin alongside the built-in ones. - -To add an external snapshot plugin, add the plugin to containerd's config file -(by default at `/etc/containerd/config.toml`). The string following -`proxy_plugin.` will be used as the name of the snapshotter and the address -should refer to a socket with a GRPC listener serving containerd's Snapshot -GRPC API. Remember to restart containerd for any configuration changes to take -effect. - -``` -[proxy_plugins] - [proxy_plugins.customsnapshot] - type = "snapshot" - address = "/var/run/mysnapshotter.sock" -``` - -See [PLUGINS.md](/docs/PLUGINS.md) for how to create plugins - -### Releases and API Stability - -Please see [RELEASES.md](RELEASES.md) for details on versioning and stability -of containerd components. - -Downloadable 64-bit Intel/AMD binaries of all official releases are available on -our [releases page](https://github.com/containerd/containerd/releases). - -For other architectures and distribution support, you will find that many -Linux distributions package their own containerd and provide it across several -architectures, such as [Canonical's Ubuntu packaging](https://launchpad.net/ubuntu/bionic/+package/containerd). - -#### Enabling command auto-completion - -Starting with containerd 1.4, the urfave client feature for auto-creation of bash and zsh -autocompletion data is enabled. To use the autocomplete feature in a bash shell for example, source -the autocomplete/ctr file in your `.bashrc`, or manually like: - -``` -$ source ./contrib/autocomplete/ctr -``` - -#### Distribution of `ctr` autocomplete for bash and zsh - -For bash, copy the `contrib/autocomplete/ctr` script into -`/etc/bash_completion.d/` and rename it to `ctr`. The `zsh_autocomplete` -file is also available and can be used similarly for zsh users. - -Provide documentation to users to `source` this file into their shell if -you don't place the autocomplete file in a location where it is automatically -loaded for the user's shell environment. - -### CRI - -`cri` is a [containerd](https://containerd.io/) plugin implementation of the Kubernetes [container runtime interface (CRI)](https://github.com/kubernetes/cri-api/blob/master/pkg/apis/runtime/v1/api.proto). With it, you are able to use containerd as the container runtime for a Kubernetes cluster. - -![cri](./docs/cri/cri.png) - -#### CRI Status - -`cri` is a native plugin of containerd. Since containerd 1.1, the cri plugin is built into the release binaries and enabled by default. - -> **Note:** As of containerd 1.5, the `cri` plugin is merged into the containerd/containerd repo. For example, the source code previously stored under [`containerd/cri/pkg`](https://github.com/containerd/cri/tree/release/1.4/pkg) -was moved to [`containerd/containerd/pkg/cri` package](https://github.com/containerd/containerd/tree/main/pkg/cri). - -The `cri` plugin has reached GA status, representing that it is: -* Feature complete -* Works with Kubernetes 1.10 and above -* Passes all [CRI validation tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/cri-validation.md). -* Passes all [node e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/e2e-node-tests.md). -* Passes all [e2e tests](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-testing/e2e-tests.md). - -See results on the containerd k8s [test dashboard](https://k8s-testgrid.appspot.com/sig-node-containerd) - -#### Validating Your `cri` Setup -A Kubernetes incubator project, [cri-tools](https://github.com/kubernetes-sigs/cri-tools), includes programs for exercising CRI implementations. More importantly, cri-tools includes the program `critest` which is used for running [CRI Validation Testing](https://github.com/kubernetes/community/blob/master/contributors/devel/sig-node/cri-validation.md). - -#### CRI Guides -* [Installing with Ansible and Kubeadm](contrib/ansible/README.md) -* [For Non-Ansible Users, Preforming a Custom Installation Using the Release Tarball and Kubeadm](docs/getting-started.md) -* [CRI Plugin Testing Guide](./docs/cri/testing.md) -* [Debugging Pods, Containers, and Images with `crictl`](./docs/cri/crictl.md) -* [Configuring `cri` Plugins](./docs/cri/config.md) -* [Configuring containerd](https://github.com/containerd/containerd/blob/main/docs/man/containerd-config.8.md) - -### Communication - -For async communication and long-running discussions please use issues and pull requests on the GitHub repo. -This will be the best place to discuss design and implementation. - -For sync communication catch us in the `#containerd` and `#containerd-dev` Slack channels on Cloud Native Computing Foundation's (CNCF) Slack - `cloud-native.slack.com`. Everyone is welcome to join and chat. [Get Invite to CNCF Slack.](https://slack.cncf.io) - -### Security audit - -Security audits for the containerd project are hosted on our website. Please see the [security page at containerd.io](https://containerd.io/security/) for more information. - -### Reporting security issues - -Please follow the instructions at [containerd/project](https://github.com/containerd/project/blob/main/SECURITY.md#reporting-a-vulnerability) - -## Licenses - -The containerd codebase is released under the [Apache 2.0 license](LICENSE). -The README.md file and files in the "docs" folder are licensed under the -Creative Commons Attribution 4.0 International License. You may obtain a -copy of the license, titled CC-BY-4.0, at http://creativecommons.org/licenses/by/4.0/. - -## Project details - -**containerd** is the primary open source project within the broader containerd GitHub organization. -However, all projects within the repo have common maintainership, governance, and contributing -guidelines which are stored in a `project` repository commonly for all containerd projects. - -Please find all these core project documents, including the: - * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md), - * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS), - * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md) - -information in our [`containerd/project`](https://github.com/containerd/project) repository. - -## Adoption - -Interested to see who is using containerd? Are you using containerd in a project? -Please add yourself via pull request to our [ADOPTERS.md](./ADOPTERS.md) file. diff --git a/vendor/github.com/containerd/containerd/RELEASES.md b/vendor/github.com/containerd/containerd/RELEASES.md deleted file mode 100644 index f2968c496b..0000000000 --- a/vendor/github.com/containerd/containerd/RELEASES.md +++ /dev/null @@ -1,455 +0,0 @@ -# Versioning and Release - -This document details the versioning and release plan for containerd. Stability -is a top goal for this project, and we hope that this document and the processes -it entails will help to achieve that. It covers the release process, versioning -numbering, backporting, API stability and support horizons. - -If you rely on containerd, it would be good to spend time understanding the -areas of the API that are and are not supported and how they impact your -project in the future. - -This document will be considered a living document. Supported timelines, -backport targets and API stability guarantees will be updated here as they -change. - -If there is something that you require or this document leaves out, please -reach out by [filing an issue](https://github.com/containerd/containerd/issues). - -## Releases - -Releases of containerd will be versioned using dotted triples, similar to -[Semantic Version](http://semver.org/). For the purposes of this document, we -will refer to the respective components of this triple as -`..`. The version number may have additional information, -such as alpha, beta and release candidate qualifications. Such releases will be -considered "pre-releases". - -### Major and Minor Releases - -Major and minor releases of containerd will be made from main. Releases of -containerd will be marked with GPG signed tags and announced at -https://github.com/containerd/containerd/releases. The tag will be of the -format `v..` and should be made with the command `git tag --s v..`. - -After a minor release, a branch will be created, with the format -`release/.` from the minor tag. All further patch releases will -be done from that branch. For example, once we release `v1.0.0`, a branch -`release/1.0` will be created from that tag. All future patch releases will be -done against that branch. - -### Pre-releases - -Pre-releases, such as alphas, betas and release candidates will be conducted -from their source branch. For major and minor releases, these releases will be -done from main. For patch releases, these pre-releases should be done within -the corresponding release branch. - -While pre-releases are done to assist in the stabilization process, no -guarantees are provided. - -### Upgrade Path - -The upgrade path for containerd is such that the 0.0.x patch releases are -always backward compatible with its major and minor version. Minor (0.x.0) -version will always be compatible with the previous minor release. i.e. 1.2.0 -is backwards compatible with 1.1.0 and 1.1.0 is compatible with 1.0.0. There is -no compatibility guarantees for upgrades that span multiple, _minor_ releases. -For example, 1.0.0 to 1.2.0 is not supported. One should first upgrade to 1.1, -then 1.2. - -There are no compatibility guarantees with upgrades to _major_ versions. For -example, upgrading from 1.0.0 to 2.0.0 may require resources to migrated or -integrations to change. Each major version will be supported for at least 1 -year with bug fixes and security patches. - -### Next Release - -The activity for the next release will be tracked in the -[milestones](https://github.com/containerd/containerd/milestones). If your -issue or PR is not present in a milestone, please reach out to the maintainers -to create the milestone or add an issue or PR to an existing milestone. - -### Support Horizon - -Support horizons will be defined corresponding to a release branch, identified -by `.`. Release branches will be in one of several states: - -- __*Next*__: The next planned release branch. -- __*Active*__: The release is a stable branch which is currently supported and accepting patches. -- __*Extended*__: The release branch is only accepting security patches. -- __*LTS*__: The release is a long term stable branch which is currently supported and accepting patches. -- __*End of Life*__: The release branch is no longer supported and no new patches will be accepted. - -Releases will be supported at least one year after a _minor_ release. This means that -we will accept bug reports and backports to release branches until the end of -life date. If no new _minor_ release has been made, that release will be -considered supported until 6 months after the next _minor_ is released or one year, -whichever is longer. Additionally, releases may have an extended security support -period after the end of the active period to accept security backports. This -timeframe will be decided by maintainers before the end of the active status. - -Long term stable (_LTS_) releases will be supported for at least three years after -their initial _minor_ release. These branches will accept bug reports and -backports until the end of life date. They may also accept a wider range of -patches than non-_LTS_ releases to support the longer term maintainability of the -branch, including library dependency, toolchain (including Go) and other version updates -which are needed to ensure each release is built with fully supported dependencies and -remains usable by containerd clients. There should be at least a 6-month overlap between -the end of life of an _LTS_ release and the initial release of a new _LTS_ release. -Up to 6 months before the announced end of life of an _LTS_ branch, the branch may -convert to a regular _Active_ release with stricter backport criteria. - -The current state is available in the following tables: - -| Release | Status | Start | End of Life | -| --------- | ------------- | ------------------ | ------------------- | -| [0.0](https://github.com/containerd/containerd/releases/tag/0.0.5) | End of Life | Dec 4, 2015 | - | -| [0.1](https://github.com/containerd/containerd/releases/tag/v0.1.0) | End of Life | Mar 21, 2016 | - | -| [0.2](https://github.com/containerd/containerd/tree/v0.2.x) | End of Life | Apr 21, 2016 | December 5, 2017 | -| [1.0](https://github.com/containerd/containerd/releases/tag/v1.0.3) | End of Life | December 5, 2017 | December 5, 2018 | -| [1.1](https://github.com/containerd/containerd/releases/tag/v1.1.8) | End of Life | April 23, 2018 | October 23, 2019 | -| [1.2](https://github.com/containerd/containerd/releases/tag/v1.2.13) | End of Life | October 24, 2018 | October 15, 2020 | -| [1.3](https://github.com/containerd/containerd/releases/tag/v1.3.10) | End of Life | September 26, 2019 | March 4, 2021 | -| [1.4](https://github.com/containerd/containerd/releases/tag/v1.4.13) | End of Life | August 17, 2020 | March 3, 2022 | -| [1.5](https://github.com/containerd/containerd/releases/tag/v1.5.18) | End of Life | May 3, 2021 | February 28, 2023 | -| [1.6](https://github.com/containerd/containerd/releases/tag/v1.6.19) | LTS | February 15, 2022 | max(February 15, 2025 or next LTS + 6 months) | -| [1.7](https://github.com/containerd/containerd/releases/tag/v1.7.0) | Active | March 10, 2023 | max(March 10, 2024 or release of 2.0 + 6 months) | -| [2.0](https://github.com/containerd/containerd/milestone/35) | Next | TBD | TBD | - - -### Kubernetes Support - -The Kubernetes version matrix represents the versions of containerd which are -recommended for a Kubernetes release. Any actively supported version of -containerd may receive patches to fix bugs encountered in any version of -Kubernetes, however, our recommendation is based on which versions have been -the most thoroughly tested. See the [Kubernetes test grid](https://testgrid.k8s.io/sig-node-containerd) -for the list of actively tested versions. Kubernetes only supports n-3 minor -release versions and containerd will ensure there is always a supported version -of containerd for every supported version of Kubernetes. - -| Kubernetes Version | containerd Version | CRI Version | -|--------------------|--------------------|-----------------| -| 1.24 | 1.7.0+, 1.6.4+ | v1, v1alpha2 | -| 1.25 | 1.7.0+, 1.6.4+ | v1, v1alpha2 ** | -| 1.26 | 1.7.0+, 1.6.15+ | v1 | - -** Note: containerd v1.6.*, and v1.7.* support CRI v1 and v1alpha2 through EOL as those releases continue to support older versions of k8s, cloud providers, and other clients using CRI v1alpha2. CRI v1alpha2 is deprecated in v1.7 and will be removed in containerd v2.0. - -Deprecated containerd and kubernetes versions - -| Containerd Version | Kubernetes Version | CRI Version | -|--------------------------|--------------------|----------------------| -| v1.0 (w/ cri-containerd) | 1.7, 1.8, 1.9 | v1alpha1 | -| v1.1 | 1.10+ | v1alpha2 | -| v1.2 | 1.10+ | v1alpha2 | -| v1.3 | 1.12+ | v1alpha2 | -| v1.4 | 1.19+ | v1alpha2 | -| v1.5 | 1.20+ | v1 (1.23+), v1alpha2 | - -### Backporting - -Backports in containerd are community driven. As maintainers, we'll try to -ensure that sensible bugfixes make it into _active_ release, but our main focus -will be features for the next _minor_ or _major_ release. For the most part, -this process is straightforward, and we are here to help make it as smooth as -possible. - -If there are important fixes that need to be backported, please let us know in -one of three ways: - -1. Open an issue. -2. Open a PR with cherry-picked change from main. -3. Open a PR with a ported fix. - -__If you are reporting a security issue:__ - -Please follow the instructions at [containerd/project](https://github.com/containerd/project/blob/main/SECURITY.md#reporting-a-vulnerability) - -Remember that backported PRs must follow the versioning guidelines from this document. - -Any release that is "active" can accept backports. Opening a backport PR is -fairly straightforward. The steps differ depending on whether you are pulling -a fix from main or need to draft a new commit specific to a particular -branch. - -To cherry-pick a straightforward commit from main, simply use the cherry-pick -process: - -1. Pick the branch to which you want backported, usually in the format - `release/.`. The following will create a branch you can - use to open a PR: - - ```console - $ git checkout -b my-backport-branch release/.. - ``` - -2. Find the commit you want backported. -3. Apply it to the release branch: - - ```console - $ git cherry-pick -xsS - ``` - (Optional) If other commits exist in the main branch which are related - to the cherry-picked commit; eg: fixes to the main PR. It is recommended - to cherry-pick those commits also into this same `my-backport-branch`. -4. Push the branch and open up a PR against the _release branch_: - - ``` - $ git push -u stevvooe my-backport-branch - ``` - - Make sure to replace `stevvooe` with whatever fork you are using to open - the PR. When you open the PR, make sure to switch `main` with whatever - release branch you are targeting with the fix. Make sure the PR title has - `[]` prefixed. e.g.: - - ``` - [release/1.4] Fix foo in bar - ``` - -If there is no existing fix in main, you should first fix the bug in main, -or ask us a maintainer or contributor to do it via an issue. Once that PR is -completed, open a PR using the process above. - -Only when the bug is not seen in main and must be made for the specific -release branch should you open a PR with new code. - -## Public API Stability - -The following table provides an overview of the components covered by -containerd versions: - - -| Component | Status | Stabilized Version | Links | -|------------------|----------|--------------------|---------------| -| GRPC API | Stable | 1.0 | [gRPC API](#grpc-api) | -| Metrics API | Stable | 1.0 | - | -| Runtime Shim API | Stable | 1.2 | - | -| Daemon Config | Stable | 1.0 | - | -| CRI GRPC API | Stable | 1.6 (_CRI v1_) | [cri-api](https://github.com/kubernetes/cri-api/tree/master/pkg/apis/runtime/v1) | -| Go client API | Unstable | _future_ | [godoc](https://godoc.org/github.com/containerd/containerd) | -| `ctr` tool | Unstable | Out of scope | - | - -From the version stated in the above table, that component must adhere to the -stability constraints expected in release versions. - -Unless explicitly stated here, components that are called out as unstable or -not covered may change in a future minor version. Breaking changes to -"unstable" components will be avoided in patch versions. - -### GRPC API - -The primary product of containerd is the GRPC API. As of the 1.0.0 release, the -GRPC API will not have any backwards incompatible changes without a _major_ -version jump. - -To ensure compatibility, we have collected the entire GRPC API symbol set into -a single file. At each _minor_ release of containerd, we will move the current -`next.pb.txt` file to a file named for the minor version, such as `1.0.pb.txt`, -enumerating the support services and messages. - -Note that new services may be added in _minor_ releases. New service methods -and new fields on messages may be added if they are optional. - -`*.pb.txt` files are generated at each API release. They prevent unintentional changes -to the API by having a diff that the CI can run. These files are not intended to be -consumed or used by clients. - -### Metrics API - -The metrics API that outputs prometheus style metrics will be versioned independently, -prefixed with the API version. i.e. `/v1/metrics`, `/v2/metrics`. - -The metrics API version will be incremented when breaking changes are made to the prometheus -output. New metrics can be added to the output in a backwards compatible manner without -bumping the API version. - -### Plugins API - -containerd is based on a modular design where plugins are implemented to provide the core functionality. -Plugins implemented in tree are supported by the containerd community unless explicitly specified as non-stable. -Out of tree plugins are not supported by the containerd maintainers. - -Currently, the Windows runtime and snapshot plugins are not stable and not supported. -Please refer to the GitHub milestones for Windows support in a future release. - -#### Error Codes - -Error codes will not change in a patch release, unless a missing error code -causes a blocking bug. Error codes of type "unknown" may change to more -specific types in the future. Any error code that is not "unknown" that is -currently returned by a service will not change without a _major_ release or a -new version of the service. - -If you find that an error code that is required by your application is not -well-documented in the protobuf service description or tested explicitly, -please file an issue and we will clarify. - -#### Opaque Fields - -Unless explicitly stated, the formats of certain fields may not be covered by -this guarantee and should be treated opaquely. For example, don't rely on the -format details of a URL field unless we explicitly say that the field will -follow that format. - -### Go client API - -The Go client API, documented in -[godoc](https://godoc.org/github.com/containerd/containerd), is currently -considered unstable. It is recommended to vendor the necessary components to -stabilize your project build. Note that because the Go API interfaces with the -GRPC API, clients written against a 1.0 Go API should remain compatible with -future 1.x series releases. - -We intend to stabilize the API in a future release when more integrations have -been carried out. - -Any changes to the API should be detectable at compile time, so upgrading will -be a matter of fixing compilation errors and moving from there. - -### CRI GRPC API - -The CRI (Container Runtime Interface) GRPC API is used by a Kubernetes kubelet -to communicate with a container runtime. This interface is used to manage -container lifecycles and container images. Currently, this API is under -development and unstable across Kubernetes releases. Each Kubernetes release -only supports a single version of CRI and the CRI plugin only implements a -single version of CRI. - -Each _minor_ release will support one version of CRI and at least one version -of Kubernetes. Once this API is stable, a _minor_ will be compatible with any -version of Kubernetes which supports that version of CRI. - -### `ctr` tool - -The `ctr` tool provides the ability to introspect and understand the containerd -API. It is not considered a primary offering of the project and is unsupported in -that sense. While we understand its value as a debug tool, it may be completely -refactored or have breaking changes in _minor_ releases. - -Targeting `ctr` for feature additions reflects a misunderstanding of the containerd -architecture. Feature addition should focus on the client Go API and additions to -`ctr` may or may not be accepted at the discretion of the maintainers. - -We will do our best to not break compatibility in the tool in _patch_ releases. - -### Daemon Configuration - -The daemon's configuration file, commonly located in `/etc/containerd/config.toml` -is versioned and backwards compatible. The `version` field in the config -file specifies the config's version. If no version number is specified inside -the config file then it is assumed to be a version 1 config and parsed as such. -Please use `version = 2` to enable version 2 config as version 1 has been -deprecated. - -### Not Covered - -As a general rule, anything not mentioned in this document is not covered by -the stability guidelines and may change in any release. Explicitly, this -pertains to this non-exhaustive list of components: - -- File System layout -- Storage formats -- Snapshot formats - -Between upgrades of subsequent, _minor_ versions, we may migrate these formats. -Any outside processes relying on details of these file system layouts may break -in that process. Container root file systems will be maintained on upgrade. - -### Exceptions - -We may make exceptions in the interest of __security patches__. If a break is -required, it will be communicated clearly and the solution will be considered -against total impact. - -## Deprecated features - -The deprecated features are shown in the following table: - -| Component | Deprecation release | Target release for removal | Recommendation | -|----------------------------------------------------------------------------------|---------------------|----------------------------|------------------------------------------| -| Runtime V1 API and implementation (`io.containerd.runtime.v1.linux`) | containerd v1.4 | containerd v2.0 | Use `io.containerd.runc.v2` | -| Runc V1 implementation of Runtime V2 (`io.containerd.runc.v1`) | containerd v1.4 | containerd v2.0 | Use `io.containerd.runc.v2` | -| config.toml `version = 1` | containerd v1.5 | containerd v2.0 | Use config.toml `version = 2` | -| Built-in `aufs` snapshotter | containerd v1.5 | containerd v2.0 | Use `overlayfs` snapshotter | -| Container label `containerd.io/restart.logpath` | containerd v1.5 | containerd v2.0 | Use `containerd.io/restart.loguri` label | -| `cri-containerd-*.tar.gz` release bundles | containerd v1.6 | containerd v2.0 | Use `containerd-*.tar.gz` bundles | -| Pulling Schema 1 images (`application/vnd.docker.distribution.manifest.v1+json`) | containerd v1.7 | containerd v2.0 | Use Schema 2 or OCI images | -| CRI `v1alpha2` | containerd v1.7 | containerd v2.0 | Use CRI `v1` | - -### Deprecated config properties -The deprecated properties in [`config.toml`](./docs/cri/config.md) are shown in the following table: - -| Property Group | Property | Deprecation release | Target release for removal | Recommendation | -|----------------------------------------------------------------------|------------------------------|---------------------|----------------------------|-------------------------------------------------| -|`[plugins."io.containerd.grpc.v1.cri"]` | `systemd_cgroup` | containerd v1.3 | containerd v2.0 | Use `SystemdCgroup` in runc options (see below) | -|`[plugins."io.containerd.grpc.v1.cri".containerd]` | `untrusted_workload_runtime` | containerd v1.2 | containerd v2.0 | Create `untrusted` runtime in `runtimes` | -|`[plugins."io.containerd.grpc.v1.cri".containerd]` | `default_runtime` | containerd v1.3 | containerd v2.0 | Use `default_runtime_name` | -|`[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.*]` | `runtime_engine` | containerd v1.3 | containerd v2.0 | Use runtime v2 | -|`[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.*]` | `runtime_root` | containerd v1.3 | containerd v2.0 | Use `options.Root` | -|`[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.*.options]` | `CriuPath` | containerd v1.7 | containerd v2.0 | Set `$PATH` to the `criu` binary | -|`[plugins."io.containerd.grpc.v1.cri".registry]` | `auths` | containerd v1.3 | containerd v2.0 | Use [`ImagePullSecrets`](https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/). See also [#8228](https://github.com/containerd/containerd/issues/8228). | -|`[plugins."io.containerd.grpc.v1.cri".registry]` | `configs` | containerd v1.5 | containerd v2.0 | Use [`config_path`](./docs/hosts.md) | -|`[plugins."io.containerd.grpc.v1.cri".registry]` | `mirrors` | containerd v1.5 | containerd v2.0 | Use [`config_path`](./docs/hosts.md) | -|`[plugins."io.containerd.tracing.processor.v1.otlp"]` | `endpoint`, `protocol`, `insecure` | containerd v1.6.29 | containerd v2.0 | Use [OTLP environment variables](https://opentelemetry.io/docs/specs/otel/protocol/exporter/), e.g. OTEL_EXPORTER_OTLP_TRACES_ENDPOINT, OTEL_EXPORTER_OTLP_PROTOCOL, OTEL_SDK_DISABLED | -|`[plugins."io.containerd.internal.v1.tracing"]` | `service_name`, `sampling_ratio` | containerd v1.6.29 | containerd v2.0 | Instead use [OTel environment variables](https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/), e.g. OTEL_SERVICE_NAME, OTEL_TRACES_SAMPLER* | - - -> **Note** -> -> CNI Config Template (`plugins."io.containerd.grpc.v1.cri".cni.conf_template`) was once deprecated in v1.7.0, -> but its deprecation was cancelled in v1.7.3. - -
Example: runc option SystemdCgroup

- -```toml -version = 2 - -# OLD -# [plugins."io.containerd.grpc.v1.cri"] -# systemd_cgroup = true - -# NEW -[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] - SystemdCgroup = true -``` - -

- -
Example: runc option Root

- -```toml -version = 2 - -# OLD -# [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc] -# runtime_root = "/path/to/runc/root" - -# NEW -[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options] - Root = "/path/to/runc/root" -``` - -

- -## Experimental features - -Experimental features are new features added to containerd which do not have the -same stability guarantees as the rest of containerd. An effort is made to avoid -breaking interfaces between versions, but changes to experimental features before -being fully supported is possible. Users can still expect experimental features -to be high quality and are encouraged to use new features to help them stabilize -more quickly. - -| Component | Initial Release | Target Supported Release | -|----------------------------------------------------------------------------------------|-----------------|--------------------------| -| [Sandbox Service](https://github.com/containerd/containerd/pull/6703) | containerd v1.7 | containerd v2.0 | -| [Sandbox CRI Server](https://github.com/containerd/containerd/pull/7228) | containerd v1.7 | containerd v2.0 | -| [Transfer Service](https://github.com/containerd/containerd/pull/7320) | containerd v1.7 | containerd v2.0 | -| [NRI in CRI Support](https://github.com/containerd/containerd/pull/6019) | containerd v1.7 | containerd v2.0 | -| [gRPC Shim](https://github.com/containerd/containerd/pull/8052) | containerd v1.7 | containerd v2.0 | -| [CRI Runtime Specific Snapshotter](https://github.com/containerd/containerd/pull/6899) | containerd v1.7 | containerd v2.0 | -| [CRI Support for User Namespaces](https://github.com/containerd/containerd/pull/7679) | containerd v1.7 | containerd v2.0 | diff --git a/vendor/github.com/containerd/containerd/ROADMAP.md b/vendor/github.com/containerd/containerd/ROADMAP.md deleted file mode 100644 index cf542e1e45..0000000000 --- a/vendor/github.com/containerd/containerd/ROADMAP.md +++ /dev/null @@ -1,28 +0,0 @@ -# containerd roadmap - -containerd uses the issues and milestones to define its roadmap. -`ROADMAP.md` files are common in open source projects, but we find they quickly become out of date. -We opt for an issues and milestone approach that our maintainers and community can keep up-to-date as work is added and completed. - -## Issues - -Issues tagged with the `roadmap` label are high level roadmap items. -They are tasks and/or features that the containerd community wants completed. - -Smaller issues and pull requests can reference back to the main roadmap issue that is tagged to help detail progress towards the overall goal. - -## Milestones - -Milestones define when an issue, pull request, and/or roadmap item is to be completed. -Issues are the what, milestones are the when. -Development is complex therefore roadmap items can move between milestones depending on the remaining development and testing required to release a change. - -## Searching - -To find the roadmap items currently planned for containerd you can filter on the `roadmap` label. - -[Search Roadmap Items](https://github.com/containerd/containerd/issues?q=is%3Aopen+is%3Aissue+label%3Aroadmap) - -After searching for roadmap items you can view what milestone they are scheduled to be completed in along with the progress. - -[View Milestones](https://github.com/containerd/containerd/milestones) diff --git a/vendor/github.com/containerd/containerd/SCOPE.md b/vendor/github.com/containerd/containerd/SCOPE.md deleted file mode 100644 index 3eb1c55fc2..0000000000 --- a/vendor/github.com/containerd/containerd/SCOPE.md +++ /dev/null @@ -1,57 +0,0 @@ -# Scope and Principles - -Having a clearly defined scope of a project is important for ensuring consistency and focus. -These following criteria will be used when reviewing pull requests, features, and changes for the project before being accepted. - -### Components - -Components should not have tight dependencies on each other so that they are able to be used independently. -The APIs for images and containers should be designed in a way that when used together the components have a natural flow but still be useful independently. - -An example for this design can be seen with the overlay filesystems and the container execution layer. -The execution layer and overlay filesystems can be used independently but if you were to use both, they share a common `Mount` struct that the filesystems produce and the execution layer consumes. - -### Primitives - -containerd should expose primitives to solve problems instead of building high level abstractions in the API. -A common example of this is how build would be implemented. -Instead of having a build API in containerd we should expose the lower level primitives that allow things required in build to work. -Breaking up the filesystem APIs to allow snapshots, copy functionality, and mounts allow people implementing build at the higher levels with more flexibility. - -### Extensibility and Defaults - -For the various components in containerd there should be defined extension points where implementations can be swapped for alternatives. -The best example of this is that containerd will use `runc` from OCI as the default runtime in the execution layer but other runtimes conforming to the OCI Runtime specification can be easily added to containerd. - -containerd will come with a default implementation for the various components. -These defaults will be chosen by the maintainers of the project and should not change unless better tech for that component comes out. -Additional implementations will not be accepted into the core repository and should be developed in a separate repository not maintained by the containerd maintainers. - - -## Scope - -The following table specifies the various components of containerd and general features of container runtimes. -The table specifies whether the feature/component is in or out of scope. - -| Name | Description | In/Out | Reason | -|------------------------------|--------------------------------------------------------------------------------------------------------|--------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| execution | Provide an extensible execution layer for executing a container | in | Create,start, stop pause, resume exec, signal, delete | -| cow filesystem | Built in functionality for overlay, aufs, and other copy on write filesystems for containers | in | | -| distribution | Having the ability to push and pull images as well as operations on images as a first class API object | in | containerd will fully support the management and retrieval of images | -| metrics | container-level metrics, cgroup stats, and OOM events | in | -| networking | creation and management of network interfaces | out | Networking will be handled and provided to containerd via higher level systems. | -| build | Building images as a first class API | out | Build is a higher level tooling feature and can be implemented in many different ways on top of containerd | -| volumes | Volume management for external data | out | The API supports mounts, binds, etc where all volumes type systems can be built on top of containerd. | -| logging | Persisting container logs | out | Logging can be build on top of containerd because the container’s STDIO will be provided to the clients and they can persist any way they see fit. There is no io copying of container STDIO in containerd. | - - -containerd is scoped to a single host and makes assumptions based on that fact. -It can be used to build things like a node agent that launches containers but does not have any concepts of a distributed system. - -containerd is designed to be embedded into a larger system, hence it only includes a barebone CLI (`ctr`) specifically for development and debugging purpose, with no mandate to be human-friendly, and no guarantee of interface stability over time. - -### How is the scope changed? - -The scope of this project is an allowed list. -If it's not mentioned as being in scope, it is out of scope. -For the scope of this project to change it requires a 100% vote from all maintainers of the project. diff --git a/vendor/github.com/containerd/containerd/Vagrantfile b/vendor/github.com/containerd/containerd/Vagrantfile deleted file mode 100644 index 2f4ff0d179..0000000000 --- a/vendor/github.com/containerd/containerd/Vagrantfile +++ /dev/null @@ -1,331 +0,0 @@ -# -*- 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 Fedora and EL -Vagrant.configure("2") do |config| - config.vm.box = ENV["BOX"] ? ENV["BOX"].split("@")[0] : "fedora/39-cloud-base" - # BOX_VERSION is deprecated. Use "BOX=@". - config.vm.box_version = ENV["BOX_VERSION"] || (ENV["BOX"].split("@")[1] if ENV["BOX"]) - - memory = 4096 - cpus = 2 - disk_size = 60 - config.vm.provider :virtualbox do |v, o| - v.memory = memory - v.cpus = cpus - # Needs env var VAGRANT_EXPERIMENTAL="disks" - o.vm.disk :disk, size: "#{disk_size}GB", primary: true - v.customize ["modifyvm", :id, "--firmware", "efi"] - end - config.vm.provider :libvirt do |v| - v.memory = memory - v.cpus = cpus - v.machine_virtual_size = disk_size - v.loader = "/usr/share/OVMF/OVMF_CODE.fd" - end - - config.vm.synced_folder ".", "/vagrant", type: "rsync" - - config.vm.provision 'shell', path: 'script/resize-vagrant-root.sh' - - # Disabled by default. To run: - # vagrant up --provision-with=upgrade-packages - # To upgrade only specific packages: - # UPGRADE_PACKAGES=selinux vagrant up --provision-with=upgrade-packages - # - config.vm.provision "upgrade-packages", type: "shell", run: "never" do |sh| - sh.upload_path = "/tmp/vagrant-upgrade-packages" - sh.env = { - 'UPGRADE_PACKAGES': ENV['UPGRADE_PACKAGES'], - } - sh.inline = <<~SHELL - #!/usr/bin/env bash - set -eux -o pipefail - dnf -y upgrade ${UPGRADE_PACKAGES} - SHELL - end - - # To re-run, installing CNI from RPM: - # INSTALL_PACKAGES="containernetworking-plugins" vagrant up --provision-with=install-packages - # - config.vm.provision "install-packages", type: "shell", run: "once" do |sh| - sh.upload_path = "/tmp/vagrant-install-packages" - sh.env = { - 'INSTALL_PACKAGES': ENV['INSTALL_PACKAGES'], - } - sh.inline = <<~SHELL - #!/usr/bin/env bash - set -eux -o pipefail - dnf -y install \ - container-selinux \ - curl \ - gcc \ - git \ - iptables \ - libseccomp-devel \ - libselinux-devel \ - lsof \ - make \ - strace \ - ${INSTALL_PACKAGES} - SHELL - end - - # EL does not have /usr/local/{bin,sbin} in the PATH by default - config.vm.provision "setup-etc-environment", type: "shell", run: "once" do |sh| - sh.upload_path = "/tmp/vagrant-setup-etc-environment" - sh.inline = <<~SHELL - #!/usr/bin/env bash - set -eux -o pipefail - cat >> /etc/environment <> /etc/profile.d/sh.local < /tmp/containerd.log - cat /tmp/containerd.log - systemctl stop containerd - } - selinux=$(getenforce) - if [[ $selinux == Enforcing ]]; then - setenforce 0 - fi - systemctl enable --now ${GOPATH}/src/github.com/containerd/containerd/containerd.service - if [[ $selinux == Enforcing ]]; then - setenforce 1 - fi - trap cleanup EXIT - ctr version - critest --parallel=$[$(nproc)+2] --ginkgo.skip='HostIpc is true' --report-dir="${REPORT_DIR}" - SHELL - end - -end diff --git a/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/api.pb.go b/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/api.pb.go new file mode 100644 index 0000000000..45c10fcecc --- /dev/null +++ b/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/api.pb.go @@ -0,0 +1,177 @@ +// To regenerate api.pb.go run `make protos` + +// Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.28.1 +// protoc v3.20.1 +// source: github.com/containerd/containerd/api/types/runtimeoptions/v1/api.proto + +package runtimeoptions + +import ( + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" +) + +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) + +type Options struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // TypeUrl specifies the type of the content inside the config file. + TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` + // ConfigPath specifies the filesystem location of the config file + // used by the runtime. + ConfigPath string `protobuf:"bytes,2,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` + // Blob specifies an in-memory TOML blob passed from containerd's configuration section + // for this runtime. This will be used if config_path is not specified. + ConfigBody []byte `protobuf:"bytes,3,opt,name=config_body,json=configBody,proto3" json:"config_body,omitempty"` +} + +func (x *Options) Reset() { + *x = Options{} + if protoimpl.UnsafeEnabled { + mi := &file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Options) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Options) ProtoMessage() {} + +func (x *Options) ProtoReflect() protoreflect.Message { + mi := &file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Options.ProtoReflect.Descriptor instead. +func (*Options) Descriptor() ([]byte, []int) { + return file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescGZIP(), []int{0} +} + +func (x *Options) GetTypeUrl() string { + if x != nil { + return x.TypeUrl + } + return "" +} + +func (x *Options) GetConfigPath() string { + if x != nil { + return x.ConfigPath + } + return "" +} + +func (x *Options) GetConfigBody() []byte { + if x != nil { + return x.ConfigBody + } + return nil +} + +var File_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto protoreflect.FileDescriptor + +var file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDesc = []byte{ + 0x0a, 0x46, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, + 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x72, 0x75, 0x6e, + 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, + 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x11, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, + 0x65, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x22, 0x66, 0x0a, 0x07, 0x4f, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, + 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, + 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x62, 0x6f, 0x64, + 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, + 0x6f, 0x64, 0x79, 0x42, 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, + 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x61, 0x70, 0x69, 0x2f, 0x74, 0x79, 0x70, 0x65, + 0x73, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x70, 0x74, 0x69, 0x6f, + 0x6e, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, +} + +var ( + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescOnce sync.Once + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescData = file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDesc +) + +func file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescGZIP() []byte { + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescOnce.Do(func() { + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescData) + }) + return file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDescData +} + +var file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_goTypes = []interface{}{ + (*Options)(nil), // 0: runtimeoptions.v1.Options +} +var file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_depIdxs = []int32{ + 0, // [0:0] is the sub-list for method output_type + 0, // [0:0] is the sub-list for method input_type + 0, // [0:0] is the sub-list for extension type_name + 0, // [0:0] is the sub-list for extension extendee + 0, // [0:0] is the sub-list for field type_name +} + +func init() { file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_init() } +func file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_init() { + if File_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Options); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDesc, + NumEnums: 0, + NumMessages: 1, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_goTypes, + DependencyIndexes: file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_depIdxs, + MessageInfos: file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_msgTypes, + }.Build() + File_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto = out.File + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_rawDesc = nil + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_goTypes = nil + file_github_com_containerd_containerd_api_types_runtimeoptions_v1_api_proto_depIdxs = nil +} diff --git a/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/api.proto b/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/api.proto similarity index 83% rename from vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/api.proto rename to vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/api.proto index d0ab0e2f95..f0a7d56b8b 100644 --- a/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/api.proto +++ b/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/api.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package runtimeoptions.v1; -option go_package = "github.com/containerd/containerd/pkg/runtimeoptions/v1;runtimeoptions_v1"; +option go_package = "github.com/containerd/containerd/api/types/runtimeoptions/v1;runtimeoptions"; message Options { // TypeUrl specifies the type of the content inside the config file. diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/doc.go b/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/doc.go similarity index 96% rename from vendor/github.com/containerd/containerd/runtime/linux/runctypes/doc.go rename to vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/doc.go index 8d074c5347..c590b9b631 100644 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/doc.go +++ b/vendor/github.com/containerd/containerd/api/types/runtimeoptions/v1/doc.go @@ -14,4 +14,4 @@ limitations under the License. */ -package runctypes +package runtimeoptions diff --git a/vendor/github.com/containerd/containerd/code-of-conduct.md b/vendor/github.com/containerd/containerd/code-of-conduct.md deleted file mode 100644 index e32b71372b..0000000000 --- a/vendor/github.com/containerd/containerd/code-of-conduct.md +++ /dev/null @@ -1,3 +0,0 @@ -## containerd Community Code of Conduct - -containerd follows the [CNCF Code of Conduct](https://github.com/cncf/foundation/blob/master/code-of-conduct.md). diff --git a/vendor/github.com/containerd/containerd/codecov.yml b/vendor/github.com/containerd/containerd/codecov.yml deleted file mode 100644 index 69cb76019a..0000000000 --- a/vendor/github.com/containerd/containerd/codecov.yml +++ /dev/null @@ -1 +0,0 @@ -comment: false diff --git a/vendor/github.com/containerd/containerd/container_opts_unix.go b/vendor/github.com/containerd/containerd/container_opts_unix.go deleted file mode 100644 index 016c1a9258..0000000000 --- a/vendor/github.com/containerd/containerd/container_opts_unix.go +++ /dev/null @@ -1,116 +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 containerd - -import ( - "context" - "fmt" - "os" - "path/filepath" - "syscall" - - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/mount" - "github.com/opencontainers/image-spec/identity" -) - -// WithRemappedSnapshot creates a new snapshot and remaps the uid/gid for the -// filesystem to be used by a container with user namespaces -func WithRemappedSnapshot(id string, i Image, uid, gid uint32) NewContainerOpts { - return withRemappedSnapshotBase(id, i, uid, gid, false) -} - -// WithRemappedSnapshotView is similar to WithRemappedSnapshot but rootfs is mounted as read-only. -func WithRemappedSnapshotView(id string, i Image, uid, gid uint32) NewContainerOpts { - return withRemappedSnapshotBase(id, i, uid, gid, true) -} - -func withRemappedSnapshotBase(id string, i Image, uid, gid uint32, readonly bool) NewContainerOpts { - return func(ctx context.Context, client *Client, c *containers.Container) error { - diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform) - if err != nil { - return err - } - - var ( - parent = identity.ChainID(diffIDs).String() - usernsID = fmt.Sprintf("%s-%d-%d", parent, uid, gid) - ) - c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter) - if err != nil { - return err - } - snapshotter, err := client.getSnapshotter(ctx, c.Snapshotter) - if err != nil { - return err - } - if _, err := snapshotter.Stat(ctx, usernsID); err == nil { - if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil { - c.SnapshotKey = id - c.Image = i.Name() - return nil - } else if !errdefs.IsNotFound(err) { - return err - } - } - mounts, err := snapshotter.Prepare(ctx, usernsID+"-remap", parent) - if err != nil { - return err - } - if err := remapRootFS(ctx, mounts, uid, gid); err != nil { - snapshotter.Remove(ctx, usernsID) - return err - } - if err := snapshotter.Commit(ctx, usernsID, usernsID+"-remap"); err != nil { - return err - } - if readonly { - _, err = snapshotter.View(ctx, id, usernsID) - } else { - _, err = snapshotter.Prepare(ctx, id, usernsID) - } - if err != nil { - return err - } - c.SnapshotKey = id - c.Image = i.Name() - return nil - } -} - -func remapRootFS(ctx context.Context, mounts []mount.Mount, uid, gid uint32) error { - return mount.WithTempMount(ctx, mounts, func(root string) error { - return filepath.Walk(root, incrementFS(root, uid, gid)) - }) -} - -func incrementFS(root string, uidInc, gidInc uint32) filepath.WalkFunc { - return func(path string, info os.FileInfo, err error) error { - if err != nil { - return err - } - var ( - stat = info.Sys().(*syscall.Stat_t) - u, g = int(stat.Uid + uidInc), int(stat.Gid + gidInc) - ) - // be sure the lchown the path as to not de-reference the symlink to a host file - return os.Lchown(path, u, g) - } -} diff --git a/vendor/github.com/containerd/containerd/containerd.service b/vendor/github.com/containerd/containerd/containerd.service deleted file mode 100644 index dcdb9f414d..0000000000 --- a/vendor/github.com/containerd/containerd/containerd.service +++ /dev/null @@ -1,42 +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. - -[Unit] -Description=containerd container runtime -Documentation=https://containerd.io -After=network.target local-fs.target dbus.service - -[Service] -#uncomment to enable the experimental sbservice (sandboxed) version of containerd/cri integration -#Environment="ENABLE_CRI_SANDBOXES=sandboxed" -ExecStartPre=-/sbin/modprobe overlay -ExecStart=/usr/local/bin/containerd - -Type=notify -Delegate=yes -KillMode=process -Restart=always -RestartSec=5 -# Having non-zero Limit*s causes performance problems due to accounting overhead -# in the kernel. We recommend using cgroups to do container-local accounting. -LimitNPROC=infinity -LimitCORE=infinity -LimitNOFILE=infinity -# Comment TasksMax if your systemd version does not supports it. -# Only systemd 226 and above support this version. -TasksMax=infinity -OOMScoreAdjust=-999 - -[Install] -WantedBy=multi-user.target diff --git a/vendor/github.com/containerd/containerd/errdefs/errors.go b/vendor/github.com/containerd/containerd/errdefs/errors.go deleted file mode 100644 index de22cadd41..0000000000 --- a/vendor/github.com/containerd/containerd/errdefs/errors.go +++ /dev/null @@ -1,72 +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 errdefs defines the common errors used throughout containerd -// packages. -// -// Use with fmt.Errorf to add context to an error. -// -// To detect an error class, use the IsXXX functions to tell whether an error -// is of a certain type. -package errdefs - -import ( - "github.com/containerd/errdefs" -) - -// Definitions of common error types used throughout containerd. All containerd -// errors returned by most packages will map into one of these errors classes. -// Packages should return errors of these types when they want to instruct a -// client to take a particular action. -// -// These errors map closely to grpc errors. -var ( - ErrUnknown = errdefs.ErrUnknown - ErrInvalidArgument = errdefs.ErrInvalidArgument - ErrNotFound = errdefs.ErrNotFound - ErrAlreadyExists = errdefs.ErrAlreadyExists - ErrPermissionDenied = errdefs.ErrPermissionDenied - ErrResourceExhausted = errdefs.ErrResourceExhausted - ErrFailedPrecondition = errdefs.ErrFailedPrecondition - ErrConflict = errdefs.ErrConflict - ErrNotModified = errdefs.ErrNotModified - ErrAborted = errdefs.ErrAborted - ErrOutOfRange = errdefs.ErrOutOfRange - ErrNotImplemented = errdefs.ErrNotImplemented - ErrInternal = errdefs.ErrInternal - ErrUnavailable = errdefs.ErrUnavailable - ErrDataLoss = errdefs.ErrDataLoss - ErrUnauthenticated = errdefs.ErrUnauthenticated - - IsCanceled = errdefs.IsCanceled - IsUnknown = errdefs.IsUnknown - IsInvalidArgument = errdefs.IsInvalidArgument - IsDeadlineExceeded = errdefs.IsDeadlineExceeded - IsNotFound = errdefs.IsNotFound - IsAlreadyExists = errdefs.IsAlreadyExists - IsPermissionDenied = errdefs.IsPermissionDenied - IsResourceExhausted = errdefs.IsResourceExhausted - IsFailedPrecondition = errdefs.IsFailedPrecondition - IsConflict = errdefs.IsConflict - IsNotModified = errdefs.IsNotModified - IsAborted = errdefs.IsAborted - IsOutOfRange = errdefs.IsOutOfRange - IsNotImplemented = errdefs.IsNotImplemented - IsInternal = errdefs.IsInternal - IsUnavailable = errdefs.IsUnavailable - IsDataLoss = errdefs.IsDataLoss - IsUnauthorized = errdefs.IsUnauthorized -) diff --git a/vendor/github.com/containerd/containerd/errdefs/grpc.go b/vendor/github.com/containerd/containerd/errdefs/grpc.go deleted file mode 100644 index 11091b1db0..0000000000 --- a/vendor/github.com/containerd/containerd/errdefs/grpc.go +++ /dev/null @@ -1,147 +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 errdefs - -import ( - "context" - "fmt" - "strings" - - "google.golang.org/grpc/codes" - "google.golang.org/grpc/status" -) - -// ToGRPC will attempt to map the backend containerd error into a grpc error, -// using the original error message as a description. -// -// Further information may be extracted from certain errors depending on their -// type. -// -// If the error is unmapped, the original error will be returned to be handled -// by the regular grpc error handling stack. -func ToGRPC(err error) error { - if err == nil { - return nil - } - - if isGRPCError(err) { - // error has already been mapped to grpc - return err - } - - switch { - case IsInvalidArgument(err): - return status.Error(codes.InvalidArgument, err.Error()) - case IsNotFound(err): - return status.Error(codes.NotFound, err.Error()) - case IsAlreadyExists(err): - return status.Error(codes.AlreadyExists, err.Error()) - case IsFailedPrecondition(err): - return status.Error(codes.FailedPrecondition, err.Error()) - case IsUnavailable(err): - return status.Error(codes.Unavailable, err.Error()) - case IsNotImplemented(err): - return status.Error(codes.Unimplemented, err.Error()) - case IsCanceled(err): - return status.Error(codes.Canceled, err.Error()) - case IsDeadlineExceeded(err): - return status.Error(codes.DeadlineExceeded, err.Error()) - } - - return err -} - -// ToGRPCf maps the error to grpc error codes, assembling the formatting string -// and combining it with the target error string. -// -// This is equivalent to errdefs.ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)) -func ToGRPCf(err error, format string, args ...interface{}) error { - return ToGRPC(fmt.Errorf("%s: %w", fmt.Sprintf(format, args...), err)) -} - -// FromGRPC returns the underlying error from a grpc service based on the grpc error code -func FromGRPC(err error) error { - if err == nil { - return nil - } - - var cls error // divide these into error classes, becomes the cause - - switch code(err) { - case codes.InvalidArgument: - cls = ErrInvalidArgument - case codes.AlreadyExists: - cls = ErrAlreadyExists - case codes.NotFound: - cls = ErrNotFound - case codes.Unavailable: - cls = ErrUnavailable - case codes.FailedPrecondition: - cls = ErrFailedPrecondition - case codes.Unimplemented: - cls = ErrNotImplemented - case codes.Canceled: - cls = context.Canceled - case codes.DeadlineExceeded: - cls = context.DeadlineExceeded - default: - cls = ErrUnknown - } - - msg := rebaseMessage(cls, err) - if msg != "" { - err = fmt.Errorf("%s: %w", msg, cls) - } else { - err = cls - } - - return err -} - -// rebaseMessage removes the repeats for an error at the end of an error -// string. This will happen when taking an error over grpc then remapping it. -// -// Effectively, we just remove the string of cls from the end of err if it -// appears there. -func rebaseMessage(cls error, err error) string { - desc := errDesc(err) - clss := cls.Error() - if desc == clss { - return "" - } - - return strings.TrimSuffix(desc, ": "+clss) -} - -func isGRPCError(err error) bool { - _, ok := status.FromError(err) - return ok -} - -func code(err error) codes.Code { - if s, ok := status.FromError(err); ok { - return s.Code() - } - return codes.Unknown -} - -func errDesc(err error) string { - if s, ok := status.FromError(err); ok { - return s.Message() - } - return err.Error() -} diff --git a/vendor/github.com/containerd/containerd/events/exchange/exchange.go b/vendor/github.com/containerd/containerd/events/exchange/exchange.go deleted file mode 100644 index b390449095..0000000000 --- a/vendor/github.com/containerd/containerd/events/exchange/exchange.go +++ /dev/null @@ -1,249 +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 exchange - -import ( - "context" - "fmt" - "strings" - "time" - - "github.com/containerd/log" - "github.com/containerd/typeurl/v2" - goevents "github.com/docker/go-events" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/events" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/identifiers" - "github.com/containerd/containerd/namespaces" -) - -// Exchange broadcasts events -type Exchange struct { - broadcaster *goevents.Broadcaster -} - -// NewExchange returns a new event Exchange -func NewExchange() *Exchange { - return &Exchange{ - broadcaster: goevents.NewBroadcaster(), - } -} - -var _ events.Publisher = &Exchange{} -var _ events.Forwarder = &Exchange{} -var _ events.Subscriber = &Exchange{} - -// Forward accepts an envelope to be directly distributed on the exchange. -// -// This is useful when an event is forwarded on behalf of another namespace or -// when the event is propagated on behalf of another publisher. -func (e *Exchange) Forward(ctx context.Context, envelope *events.Envelope) (err error) { - if err := validateEnvelope(envelope); err != nil { - return err - } - - defer func() { - logger := log.G(ctx).WithFields(log.Fields{ - "topic": envelope.Topic, - "ns": envelope.Namespace, - "type": envelope.Event.GetTypeUrl(), - }) - - if err != nil { - logger.WithError(err).Error("error forwarding event") - } else { - logger.Trace("event forwarded") - } - }() - - return e.broadcaster.Write(envelope) -} - -// Publish packages and sends an event. The caller will be considered the -// initial publisher of the event. This means the timestamp will be calculated -// at this point and this method may read from the calling context. -func (e *Exchange) Publish(ctx context.Context, topic string, event events.Event) (err error) { - var ( - namespace string - envelope events.Envelope - ) - - namespace, err = namespaces.NamespaceRequired(ctx) - if err != nil { - return fmt.Errorf("failed publishing event: %w", err) - } - if err := validateTopic(topic); err != nil { - return fmt.Errorf("envelope topic %q: %w", topic, err) - } - - encoded, err := typeurl.MarshalAny(event) - if err != nil { - return err - } - - envelope.Timestamp = time.Now().UTC() - envelope.Namespace = namespace - envelope.Topic = topic - envelope.Event = encoded - - defer func() { - logger := log.G(ctx).WithFields(log.Fields{ - "topic": envelope.Topic, - "ns": envelope.Namespace, - "type": envelope.Event.GetTypeUrl(), - }) - - if err != nil { - logger.WithError(err).Error("error publishing event") - } else { - logger.Trace("event published") - } - }() - - return e.broadcaster.Write(&envelope) -} - -// Subscribe to events on the exchange. Events are sent through the returned -// channel ch. If an error is encountered, it will be sent on channel errs and -// errs will be closed. To end the subscription, cancel the provided context. -// -// Zero or more filters may be provided as strings. Only events that match -// *any* of the provided filters will be sent on the channel. The filters use -// the standard containerd filters package syntax. -func (e *Exchange) Subscribe(ctx context.Context, fs ...string) (ch <-chan *events.Envelope, errs <-chan error) { - var ( - evch = make(chan *events.Envelope) - errq = make(chan error, 1) - channel = goevents.NewChannel(0) - queue = goevents.NewQueue(channel) - dst goevents.Sink = queue - ) - - closeAll := func() { - channel.Close() - queue.Close() - e.broadcaster.Remove(dst) - close(errq) - } - - ch = evch - errs = errq - - if len(fs) > 0 { - filter, err := filters.ParseAll(fs...) - if err != nil { - errq <- fmt.Errorf("failed parsing subscription filters: %w", err) - closeAll() - return - } - - dst = goevents.NewFilter(queue, goevents.MatcherFunc(func(gev goevents.Event) bool { - return filter.Match(adapt(gev)) - })) - } - - e.broadcaster.Add(dst) - - go func() { - defer closeAll() - - var err error - loop: - for { - select { - case ev := <-channel.C: - env, ok := ev.(*events.Envelope) - if !ok { - // TODO(stevvooe): For the most part, we are well protected - // from this condition. Both Forward and Publish protect - // from this. - err = fmt.Errorf("invalid envelope encountered %#v; please file a bug", ev) - break - } - - select { - case evch <- env: - case <-ctx.Done(): - break loop - } - case <-ctx.Done(): - break loop - } - } - - if err == nil { - if cerr := ctx.Err(); cerr != context.Canceled { - err = cerr - } - } - - errq <- err - }() - - return -} - -func validateTopic(topic string) error { - if topic == "" { - return fmt.Errorf("must not be empty: %w", errdefs.ErrInvalidArgument) - } - - if topic[0] != '/' { - return fmt.Errorf("must start with '/': %w", errdefs.ErrInvalidArgument) - } - - if len(topic) == 1 { - return fmt.Errorf("must have at least one component: %w", errdefs.ErrInvalidArgument) - } - - components := strings.Split(topic[1:], "/") - for _, component := range components { - if err := identifiers.Validate(component); err != nil { - return fmt.Errorf("failed validation on component %q: %w", component, err) - } - } - - return nil -} - -func validateEnvelope(envelope *events.Envelope) error { - if err := identifiers.Validate(envelope.Namespace); err != nil { - return fmt.Errorf("event envelope has invalid namespace: %w", err) - } - - if err := validateTopic(envelope.Topic); err != nil { - return fmt.Errorf("envelope topic %q: %w", envelope.Topic, err) - } - - if envelope.Timestamp.IsZero() { - return fmt.Errorf("timestamp must be set on forwarded event: %w", errdefs.ErrInvalidArgument) - } - - return nil -} - -func adapt(ev interface{}) filters.Adaptor { - if adaptor, ok := ev.(filters.Adaptor); ok { - return adaptor - } - - return filters.AdapterFunc(func(fieldpath []string) (string, bool) { - return "", false - }) -} diff --git a/vendor/github.com/containerd/containerd/mount/mount_unix.go b/vendor/github.com/containerd/containerd/mount/mount_unix.go deleted file mode 100644 index 46dfd1c343..0000000000 --- a/vendor/github.com/containerd/containerd/mount/mount_unix.go +++ /dev/null @@ -1,61 +0,0 @@ -//go:build !windows && !darwin && !openbsd - -/* - 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 mount - -import ( - "sort" - - "github.com/moby/sys/mountinfo" -) - -// UnmountRecursive unmounts the target and all mounts underneath, starting -// with the deepest mount first. -func UnmountRecursive(target string, flags int) error { - if target == "" { - return nil - } - mounts, err := mountinfo.GetMounts(mountinfo.PrefixFilter(target)) - if err != nil { - return err - } - - targetSet := make(map[string]struct{}) - for _, m := range mounts { - targetSet[m.Mountpoint] = struct{}{} - } - - var targets []string - for m := range targetSet { - targets = append(targets, m) - } - - // Make the deepest mount be first - sort.SliceStable(targets, func(i, j int) bool { - return len(targets[i]) > len(targets[j]) - }) - - for i, target := range targets { - if err := UnmountAll(target, flags); err != nil { - if i == len(targets)-1 { // last mount - return err - } - } - } - return nil -} diff --git a/vendor/github.com/containerd/containerd/pkg/deprecation/deprecation.go b/vendor/github.com/containerd/containerd/pkg/deprecation/deprecation.go deleted file mode 100644 index 813a0da3ae..0000000000 --- a/vendor/github.com/containerd/containerd/pkg/deprecation/deprecation.go +++ /dev/null @@ -1,105 +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 deprecation - -type Warning string - -const ( - // Prefix is a standard prefix for all Warnings, used for filtering plugin Exports - Prefix = "io.containerd.deprecation/" - // PullSchema1Image is a warning for the use of schema 1 images - PullSchema1Image Warning = Prefix + "pull-schema-1-image" - // GoPluginLibrary is a warning for the use of dynamic library Go plugins - GoPluginLibrary Warning = Prefix + "go-plugin-library" - // CRISystemdCgroupV1 is a warning for the `systemd_cgroup` property - CRISystemdCgroupV1 Warning = Prefix + "cri-systemd-cgroup-v1" - // CRIUntrustedWorkloadRuntime is a warning for the `untrusted_workload_runtime` property - CRIUntrustedWorkloadRuntime Warning = Prefix + "cri-untrusted-workload-runtime" - // CRIDefaultRuntime is a warning for the `default_runtime` property - CRIDefaultRuntime Warning = Prefix + "cri-default-runtime" - // CRIRuntimeEngine is a warning for the `runtime_engine` property - CRIRuntimeEngine Warning = Prefix + "cri-runtime-engine" - // CRIRuntimeRoot is a warning for the `runtime_root` property - CRIRuntimeRoot Warning = Prefix + "cri-runtime-root" - // CRIRegistryMirrors is a warning for the use of the `mirrors` property - CRIRegistryMirrors Warning = Prefix + "cri-registry-mirrors" - // CRIRegistryAuths is a warning for the use of the `auths` property - CRIRegistryAuths Warning = Prefix + "cri-registry-auths" - // CRIRegistryConfigs is a warning for the use of the `configs` property - CRIRegistryConfigs Warning = Prefix + "cri-registry-configs" - // CRIAPIV1Alpha2 is a warning for the use of CRI-API v1alpha2 - CRIAPIV1Alpha2 Warning = Prefix + "cri-api-v1alpha2" - // AUFSSnapshotter is a warning for the use of the aufs snapshotter - AUFSSnapshotter Warning = Prefix + "aufs-snapshotter" - // RestartLogpath is a warning for the containerd.io/restart.logpath label - RestartLogpath Warning = Prefix + "restart-logpath" - // RuntimeV1 is a warning for the io.containerd.runtime.v1.linux runtime - RuntimeV1 Warning = Prefix + "runtime-v1" - // RuntimeRuncV1 is a warning for the io.containerd.runc.v1 runtime - RuntimeRuncV1 Warning = Prefix + "runtime-runc-v1" - // CRICRIUPath is a warning for the use of the `CriuPath` property - CRICRIUPath Warning = Prefix + "cri-criu-path" - // OTLPTracingConfig is a warning for the use of the `otlp` property - TracingOTLPConfig Warning = Prefix + "tracing-processor-config" - // TracingServiceConfig is a warning for the use of the `tracing` property - TracingServiceConfig Warning = Prefix + "tracing-service-config" -) - -var messages = map[Warning]string{ - PullSchema1Image: "Schema 1 images are deprecated since containerd v1.7 and removed in containerd v2.0. " + - `Since containerd v1.7.8, schema 1 images are identified by the "io.containerd.image/converted-docker-schema1" label.`, - GoPluginLibrary: "Dynamically-linked Go plugins as containerd runtimes will be deprecated in containerd v2.0 and removed in containerd v2.1.", - CRISystemdCgroupV1: "The `systemd_cgroup` property (old form) of `[plugins.\"io.containerd.grpc.v1.cri\"] is deprecated since containerd v1.3 and will be removed in containerd v2.0. " + - "Use `SystemdCgroup` in [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.runc.options] options instead.", - CRIUntrustedWorkloadRuntime: "The `untrusted_workload_runtime` property of [plugins.\"io.containerd.grpc.v1.cri\".containerd] is deprecated since containerd v1.2 and will be removed in containerd v2.0. " + - "Create an `untrusted` runtime in `runtimes` instead.", - CRIDefaultRuntime: "The `default_runtime` property of [plugins.\"io.containerd.grpc.v1.cri\".containerd] is deprecated since containerd v1.3 and will be removed in containerd v2.0. " + - "Use `default_runtime_name` instead.", - CRIRuntimeEngine: "The `runtime_engine` property of [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.*] is deprecated since containerd v1.3 and will be removed in containerd v2.0. " + - "Use a v2 runtime and `options` instead.", - CRIRuntimeRoot: "The `runtime_root` property of [plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.*] is deprecated since containerd v1.3 and will be removed in containerd v2.0. " + - "Use a v2 runtime and `options.Root` instead.", - CRIRegistryMirrors: "The `mirrors` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.1. " + - "Use `config_path` instead.", - CRIRegistryAuths: "The `auths` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.3 and will be removed in containerd v2.1. " + - "Use `ImagePullSecrets` instead.", - CRIRegistryConfigs: "The `configs` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.1. " + - "Use `config_path` instead.", - CRIAPIV1Alpha2: "CRI API v1alpha2 is deprecated since containerd v1.7 and removed in containerd v2.0. Use CRI API v1 instead.", - AUFSSnapshotter: "The aufs snapshotter is deprecated since containerd v1.5 and removed in containerd v2.0. Use the overlay snapshotter instead.", - RestartLogpath: "The `containerd.io/restart.logpath` label is deprecated since containerd v1.5 and removed in containerd v2.0. Use `containerd.io/restart.loguri` instead.", - RuntimeV1: "The `io.containerd.runtime.v1.linux` runtime is deprecated since containerd v1.4 and removed in containerd v2.0. Use the `io.containerd.runc.v2` runtime instead.", - RuntimeRuncV1: "The `io.containerd.runc.v1` runtime is deprecated since containerd v1.4 and removed in containerd v2.0. Use the `io.containerd.runc.v2` runtime instead.", - CRICRIUPath: "The `CriuPath` property of `[plugins.\"io.containerd.grpc.v1.cri\".containerd.runtimes.*.options]` is deprecated since containerd v1.7 and will be removed in containerd v2.0. " + - "Use a criu binary in $PATH instead.", - TracingOTLPConfig: "The `otlp` property of `[plugins.\"io.containerd.tracing.processor.v1\".otlp]` is deprecated since containerd v1.6 and will be removed in containerd v2.0." + - "Use OTLP environment variables instead: https://opentelemetry.io/docs/specs/otel/protocol/exporter/", - TracingServiceConfig: "The `tracing` property of `[plugins.\"io.containerd.internal.v1\".tracing]` is deprecated since containerd v1.6 and will be removed in containerd v2.0." + - "Use OTEL environment variables instead: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/", -} - -// Valid checks whether a given Warning is valid -func Valid(id Warning) bool { - _, ok := messages[id] - return ok -} - -// Message returns the human-readable message for a given Warning -func Message(id Warning) (string, bool) { - msg, ok := messages[id] - return msg, ok -} diff --git a/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/api.pb.go b/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/api.pb.go deleted file mode 100644 index 8a30127be2..0000000000 --- a/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/api.pb.go +++ /dev/null @@ -1,177 +0,0 @@ -// To regenerate api.pb.go run `make protos` - -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.20.1 -// source: github.com/containerd/containerd/pkg/runtimeoptions/v1/api.proto - -package runtimeoptions_v1 - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type Options struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - // TypeUrl specifies the type of the content inside the config file. - TypeUrl string `protobuf:"bytes,1,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"` - // ConfigPath specifies the filesystem location of the config file - // used by the runtime. - ConfigPath string `protobuf:"bytes,2,opt,name=config_path,json=configPath,proto3" json:"config_path,omitempty"` - // Blob specifies an in-memory TOML blob passed from containerd's configuration section - // for this runtime. This will be used if config_path is not specified. - ConfigBody []byte `protobuf:"bytes,3,opt,name=config_body,json=configBody,proto3" json:"config_body,omitempty"` -} - -func (x *Options) Reset() { - *x = Options{} - if protoimpl.UnsafeEnabled { - mi := &file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *Options) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*Options) ProtoMessage() {} - -func (x *Options) ProtoReflect() protoreflect.Message { - mi := &file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use Options.ProtoReflect.Descriptor instead. -func (*Options) Descriptor() ([]byte, []int) { - return file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescGZIP(), []int{0} -} - -func (x *Options) GetTypeUrl() string { - if x != nil { - return x.TypeUrl - } - return "" -} - -func (x *Options) GetConfigPath() string { - if x != nil { - return x.ConfigPath - } - return "" -} - -func (x *Options) GetConfigBody() []byte { - if x != nil { - return x.ConfigBody - } - return nil -} - -var File_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto protoreflect.FileDescriptor - -var file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDesc = []byte{ - 0x0a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x2f, 0x61, 0x70, 0x69, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x12, 0x11, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x70, 0x74, 0x69, 0x6f, - 0x6e, 0x73, 0x2e, 0x76, 0x31, 0x22, 0x66, 0x0a, 0x07, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, - 0x12, 0x19, 0x0a, 0x08, 0x74, 0x79, 0x70, 0x65, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x07, 0x74, 0x79, 0x70, 0x65, 0x55, 0x72, 0x6c, 0x12, 0x1f, 0x0a, 0x0b, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1f, 0x0a, 0x0b, - 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x0c, 0x52, 0x0a, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x42, 0x6f, 0x64, 0x79, 0x42, 0x4a, 0x5a, - 0x48, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, - 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x64, 0x2f, 0x70, 0x6b, 0x67, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6f, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x76, 0x31, 0x3b, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x6f, - 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x76, 0x31, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x33, -} - -var ( - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescOnce sync.Once - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescData = file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDesc -) - -func file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescGZIP() []byte { - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescOnce.Do(func() { - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescData) - }) - return file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDescData -} - -var file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_msgTypes = make([]protoimpl.MessageInfo, 1) -var file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_goTypes = []interface{}{ - (*Options)(nil), // 0: runtimeoptions.v1.Options -} -var file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_init() } -func file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_init() { - if File_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Options); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDesc, - NumEnums: 0, - NumMessages: 1, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_goTypes, - DependencyIndexes: file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_depIdxs, - MessageInfos: file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_msgTypes, - }.Build() - File_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto = out.File - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_rawDesc = nil - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_goTypes = nil - file_github_com_containerd_containerd_pkg_runtimeoptions_v1_api_proto_depIdxs = nil -} diff --git a/vendor/github.com/containerd/containerd/plugin/plugin.go b/vendor/github.com/containerd/containerd/plugin/plugin.go deleted file mode 100644 index 7c854fdc3f..0000000000 --- a/vendor/github.com/containerd/containerd/plugin/plugin.go +++ /dev/null @@ -1,242 +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 plugin - -import ( - "errors" - "fmt" - "sync" -) - -var ( - // ErrNoType is returned when no type is specified - ErrNoType = errors.New("plugin: no type") - // ErrNoPluginID is returned when no id is specified - ErrNoPluginID = errors.New("plugin: no id") - // ErrIDRegistered is returned when a duplicate id is already registered - ErrIDRegistered = errors.New("plugin: id already registered") - // ErrSkipPlugin is used when a plugin is not initialized and should not be loaded, - // this allows the plugin loader differentiate between a plugin which is configured - // not to load and one that fails to load. - ErrSkipPlugin = errors.New("skip plugin") - - // ErrInvalidRequires will be thrown if the requirements for a plugin are - // defined in an invalid manner. - ErrInvalidRequires = errors.New("invalid requires") -) - -// IsSkipPlugin returns true if the error is skipping the plugin -func IsSkipPlugin(err error) bool { - return errors.Is(err, ErrSkipPlugin) -} - -// Type is the type of the plugin -type Type string - -func (t Type) String() string { return string(t) } - -const ( - // InternalPlugin implements an internal plugin to containerd - InternalPlugin Type = "io.containerd.internal.v1" - // RuntimePlugin implements a runtime - RuntimePlugin Type = "io.containerd.runtime.v1" - // RuntimePluginV2 implements a runtime v2 - RuntimePluginV2 Type = "io.containerd.runtime.v2" - // ServicePlugin implements a internal service - ServicePlugin Type = "io.containerd.service.v1" - // GRPCPlugin implements a grpc service - GRPCPlugin Type = "io.containerd.grpc.v1" - // TTRPCPlugin implements a ttrpc shim service - TTRPCPlugin Type = "io.containerd.ttrpc.v1" - // SnapshotPlugin implements a snapshotter - SnapshotPlugin Type = "io.containerd.snapshotter.v1" - // TaskMonitorPlugin implements a task monitor - TaskMonitorPlugin Type = "io.containerd.monitor.v1" - // DiffPlugin implements a differ - DiffPlugin Type = "io.containerd.differ.v1" - // MetadataPlugin implements a metadata store - MetadataPlugin Type = "io.containerd.metadata.v1" - // ContentPlugin implements a content store - ContentPlugin Type = "io.containerd.content.v1" - // GCPlugin implements garbage collection policy - GCPlugin Type = "io.containerd.gc.v1" - // EventPlugin implements event handling - EventPlugin Type = "io.containerd.event.v1" - // LeasePlugin implements lease manager - LeasePlugin Type = "io.containerd.lease.v1" - // Streaming implements a stream manager - StreamingPlugin Type = "io.containerd.streaming.v1" - // TracingProcessorPlugin implements a open telemetry span processor - TracingProcessorPlugin Type = "io.containerd.tracing.processor.v1" - // NRIApiPlugin implements the NRI adaptation interface for containerd. - NRIApiPlugin Type = "io.containerd.nri.v1" - // TransferPlugin implements a transfer service - TransferPlugin Type = "io.containerd.transfer.v1" - // SandboxStorePlugin implements a sandbox store - SandboxStorePlugin Type = "io.containerd.sandbox.store.v1" - // SandboxControllerPlugin implements a sandbox controller - SandboxControllerPlugin Type = "io.containerd.sandbox.controller.v1" - // WarningPlugin implements a warning service - WarningPlugin Type = "io.containerd.warning.v1" -) - -const ( - // RuntimeLinuxV1 is the legacy linux runtime - RuntimeLinuxV1 = "io.containerd.runtime.v1.linux" - // RuntimeRuncV1 is the runc runtime that supports a single container - RuntimeRuncV1 = "io.containerd.runc.v1" - // RuntimeRuncV2 is the runc runtime that supports multiple containers per shim - RuntimeRuncV2 = "io.containerd.runc.v2" - DeprecationsPlugin = "deprecations" -) - -const ( - SnapshotterRootDir = "root" -) - -// Registration contains information for registering a plugin -type Registration struct { - // Type of the plugin - Type Type - // ID of the plugin - ID string - // Config specific to the plugin - Config interface{} - // Requires is a list of plugins that the registered plugin requires to be available - Requires []Type - - // InitFn is called when initializing a plugin. The registration and - // context are passed in. The init function may modify the registration to - // add exports, capabilities and platform support declarations. - InitFn func(*InitContext) (interface{}, error) - // Disable the plugin from loading - Disable bool -} - -// Init the registered plugin -func (r *Registration) Init(ic *InitContext) *Plugin { - p, err := r.InitFn(ic) - return &Plugin{ - Registration: r, - Config: ic.Config, - Meta: ic.Meta, - instance: p, - err: err, - } -} - -// URI returns the full plugin URI -func (r *Registration) URI() string { - return fmt.Sprintf("%s.%s", r.Type, r.ID) -} - -var register = struct { - sync.RWMutex - r []*Registration -}{} - -// Load loads all plugins at the provided path into containerd -func Load(path string) (count int, err error) { - defer func() { - if v := recover(); v != nil { - rerr, ok := v.(error) - if !ok { - rerr = fmt.Errorf("%s", v) - } - err = rerr - } - }() - return loadPlugins(path) -} - -// Register allows plugins to register -func Register(r *Registration) { - register.Lock() - defer register.Unlock() - - if r.Type == "" { - panic(ErrNoType) - } - if r.ID == "" { - panic(ErrNoPluginID) - } - if err := checkUnique(r); err != nil { - panic(err) - } - - for _, requires := range r.Requires { - if requires == "*" && len(r.Requires) != 1 { - panic(ErrInvalidRequires) - } - } - - register.r = append(register.r, r) -} - -func checkUnique(r *Registration) error { - for _, registered := range register.r { - if r.URI() == registered.URI() { - return fmt.Errorf("%s: %w", r.URI(), ErrIDRegistered) - } - } - return nil -} - -// DisableFilter filters out disabled plugins -type DisableFilter func(r *Registration) bool - -// Graph returns an ordered list of registered plugins for initialization. -// Plugins in disableList specified by id will be disabled. -func Graph(filter DisableFilter) (ordered []*Registration) { - register.RLock() - defer register.RUnlock() - - for _, r := range register.r { - if filter(r) { - r.Disable = true - } - } - - added := map[*Registration]bool{} - for _, r := range register.r { - if r.Disable { - continue - } - children(r, added, &ordered) - if !added[r] { - ordered = append(ordered, r) - added[r] = true - } - } - return ordered -} - -func children(reg *Registration, added map[*Registration]bool, ordered *[]*Registration) { - for _, t := range reg.Requires { - for _, r := range register.r { - if !r.Disable && - r.URI() != reg.URI() && - (t == "*" || r.Type == t) { - children(r, added, ordered) - if !added[r] { - *ordered = append(*ordered, r) - added[r] = true - } - } - } - } -} diff --git a/vendor/github.com/containerd/containerd/plugin/plugin_go18.go b/vendor/github.com/containerd/containerd/plugin/plugin_go18.go deleted file mode 100644 index 70034b6f2b..0000000000 --- a/vendor/github.com/containerd/containerd/plugin/plugin_go18.go +++ /dev/null @@ -1,65 +0,0 @@ -//go:build go1.8 && !windows && amd64 && !static_build && !gccgo && !no_dynamic_plugins - -/* - 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 plugin - -import ( - "fmt" - "path/filepath" - "plugin" - "runtime" -) - -// loadPlugins loads all plugins for the OS and Arch that containerd is built -// for inside the provided path and returns the count of successfully-loaded -// plugins -func loadPlugins(path string) (int, error) { - abs, err := filepath.Abs(path) - if err != nil { - return 0, err - } - pattern := filepath.Join(abs, fmt.Sprintf( - "*-%s-%s.%s", - runtime.GOOS, - runtime.GOARCH, - getLibExt(), - )) - libs, err := filepath.Glob(pattern) - if err != nil { - return 0, err - } - loaded := 0 - for _, lib := range libs { - if _, err := plugin.Open(lib); err != nil { - return loaded, err - } - loaded++ - } - return loaded, nil -} - -// getLibExt returns a platform specific lib extension for -// the platform that containerd is running on -func getLibExt() string { - switch runtime.GOOS { - case "windows": - return "dll" - default: - return "so" - } -} diff --git a/vendor/github.com/containerd/containerd/protobuf/any.go b/vendor/github.com/containerd/containerd/protobuf/any.go deleted file mode 100644 index 84da2a33da..0000000000 --- a/vendor/github.com/containerd/containerd/protobuf/any.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 protobuf - -import ( - "github.com/containerd/typeurl/v2" - "google.golang.org/protobuf/types/known/anypb" -) - -// FromAny converts typeurl.Any to github.com/containerd/containerd/protobuf/types.Any. -func FromAny(from typeurl.Any) *anypb.Any { - if from == nil { - return nil - } - - if pbany, ok := from.(*anypb.Any); ok { - return pbany - } - - return &anypb.Any{ - TypeUrl: from.GetTypeUrl(), - Value: from.GetValue(), - } -} - -// FromAny converts an arbitrary interface to github.com/containerd/containerd/protobuf/types.Any. -func MarshalAnyToProto(from interface{}) (*anypb.Any, error) { - any, err := typeurl.MarshalAny(from) - if err != nil { - return nil, err - } - return FromAny(any), nil -} diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/1.0.pb.txt b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/1.0.pb.txt deleted file mode 100644 index 05f41fada3..0000000000 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/1.0.pb.txt +++ /dev/null @@ -1,183 +0,0 @@ -file { - name: "github.com/containerd/containerd/linux/runctypes/runc.proto" - package: "containerd.linux.runc" - dependency: "gogoproto/gogo.proto" - message_type { - name: "RuncOptions" - field { - name: "runtime" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "runtime" - } - field { - name: "runtime_root" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "runtimeRoot" - } - field { - name: "criu_path" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "criuPath" - } - field { - name: "systemd_cgroup" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "systemdCgroup" - } - } - message_type { - name: "CreateOptions" - field { - name: "no_pivot_root" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "noPivotRoot" - } - field { - name: "open_tcp" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "openTcp" - } - field { - name: "external_unix_sockets" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "externalUnixSockets" - } - field { - name: "terminal" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "terminal" - } - field { - name: "file_locks" - number: 5 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "fileLocks" - } - field { - name: "empty_namespaces" - number: 6 - label: LABEL_REPEATED - type: TYPE_STRING - json_name: "emptyNamespaces" - } - field { - name: "cgroups_mode" - number: 7 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "cgroupsMode" - } - field { - name: "no_new_keyring" - number: 8 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "noNewKeyring" - } - field { - name: "shim_cgroup" - number: 9 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "shimCgroup" - } - field { - name: "io_uid" - number: 10 - label: LABEL_OPTIONAL - type: TYPE_UINT32 - json_name: "ioUid" - } - field { - name: "io_gid" - number: 11 - label: LABEL_OPTIONAL - type: TYPE_UINT32 - json_name: "ioGid" - } - } - message_type { - name: "CheckpointOptions" - field { - name: "exit" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "exit" - } - field { - name: "open_tcp" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "openTcp" - } - field { - name: "external_unix_sockets" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "externalUnixSockets" - } - field { - name: "terminal" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "terminal" - } - field { - name: "file_locks" - number: 5 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "fileLocks" - } - field { - name: "empty_namespaces" - number: 6 - label: LABEL_REPEATED - type: TYPE_STRING - json_name: "emptyNamespaces" - } - field { - name: "cgroups_mode" - number: 7 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "cgroupsMode" - } - } - message_type { - name: "ProcessDetails" - field { - name: "exec_id" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "execId" - } - } - options { - go_package: "github.com/containerd/containerd/linux/runctypes;runctypes" - } - weak_dependency: 0 - syntax: "proto3" -} diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/next.pb.txt b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/next.pb.txt deleted file mode 100644 index eb94415b42..0000000000 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/next.pb.txt +++ /dev/null @@ -1,212 +0,0 @@ -file { - name: "github.com/containerd/containerd/runtime/linux/runctypes/runc.proto" - package: "containerd.linux.runc" - message_type { - name: "RuncOptions" - field { - name: "runtime" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "runtime" - } - field { - name: "runtime_root" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "runtimeRoot" - } - field { - name: "criu_path" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_STRING - options { - deprecated: true - } - json_name: "criuPath" - } - field { - name: "systemd_cgroup" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "systemdCgroup" - } - } - message_type { - name: "CreateOptions" - field { - name: "no_pivot_root" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "noPivotRoot" - } - field { - name: "open_tcp" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "openTcp" - } - field { - name: "external_unix_sockets" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "externalUnixSockets" - } - field { - name: "terminal" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "terminal" - } - field { - name: "file_locks" - number: 5 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "fileLocks" - } - field { - name: "empty_namespaces" - number: 6 - label: LABEL_REPEATED - type: TYPE_STRING - json_name: "emptyNamespaces" - } - field { - name: "cgroups_mode" - number: 7 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "cgroupsMode" - } - field { - name: "no_new_keyring" - number: 8 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "noNewKeyring" - } - field { - name: "shim_cgroup" - number: 9 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "shimCgroup" - } - field { - name: "io_uid" - number: 10 - label: LABEL_OPTIONAL - type: TYPE_UINT32 - json_name: "ioUid" - } - field { - name: "io_gid" - number: 11 - label: LABEL_OPTIONAL - type: TYPE_UINT32 - json_name: "ioGid" - } - field { - name: "criu_work_path" - number: 12 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "criuWorkPath" - } - field { - name: "criu_image_path" - number: 13 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "criuImagePath" - } - } - message_type { - name: "CheckpointOptions" - field { - name: "exit" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "exit" - } - field { - name: "open_tcp" - number: 2 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "openTcp" - } - field { - name: "external_unix_sockets" - number: 3 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "externalUnixSockets" - } - field { - name: "terminal" - number: 4 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "terminal" - } - field { - name: "file_locks" - number: 5 - label: LABEL_OPTIONAL - type: TYPE_BOOL - json_name: "fileLocks" - } - field { - name: "empty_namespaces" - number: 6 - label: LABEL_REPEATED - type: TYPE_STRING - json_name: "emptyNamespaces" - } - field { - name: "cgroups_mode" - number: 7 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "cgroupsMode" - } - field { - name: "work_path" - number: 8 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "workPath" - } - field { - name: "image_path" - number: 9 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "imagePath" - } - } - message_type { - name: "ProcessDetails" - field { - name: "exec_id" - number: 1 - label: LABEL_OPTIONAL - type: TYPE_STRING - json_name: "execId" - } - } - options { - go_package: "github.com/containerd/containerd/runtime/linux/runctypes;runctypes" - } - syntax: "proto3" -} diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go deleted file mode 100644 index 37f3329bce..0000000000 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.pb.go +++ /dev/null @@ -1,581 +0,0 @@ -// Code generated by protoc-gen-go. DO NOT EDIT. -// versions: -// protoc-gen-go v1.28.1 -// protoc v3.20.1 -// source: github.com/containerd/containerd/runtime/linux/runctypes/runc.proto - -package runctypes - -import ( - protoreflect "google.golang.org/protobuf/reflect/protoreflect" - protoimpl "google.golang.org/protobuf/runtime/protoimpl" - reflect "reflect" - sync "sync" -) - -const ( - // Verify that this generated code is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) - // Verify that runtime/protoimpl is sufficiently up-to-date. - _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) -) - -type RuncOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Runtime string `protobuf:"bytes,1,opt,name=runtime,proto3" json:"runtime,omitempty"` - RuntimeRoot string `protobuf:"bytes,2,opt,name=runtime_root,json=runtimeRoot,proto3" json:"runtime_root,omitempty"` - // criu binary path. - // - // Deprecated: runc option --criu is now ignored (with a warning), and the - // option will be removed entirely in a future release. Users who need a non- - // standard criu binary should rely on the standard way of looking up binaries - // in $PATH. - // - // Deprecated: Do not use. - CriuPath string `protobuf:"bytes,3,opt,name=criu_path,json=criuPath,proto3" json:"criu_path,omitempty"` - SystemdCgroup bool `protobuf:"varint,4,opt,name=systemd_cgroup,json=systemdCgroup,proto3" json:"systemd_cgroup,omitempty"` -} - -func (x *RuncOptions) Reset() { - *x = RuncOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[0] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *RuncOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*RuncOptions) ProtoMessage() {} - -func (x *RuncOptions) ProtoReflect() protoreflect.Message { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[0] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use RuncOptions.ProtoReflect.Descriptor instead. -func (*RuncOptions) Descriptor() ([]byte, []int) { - return file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescGZIP(), []int{0} -} - -func (x *RuncOptions) GetRuntime() string { - if x != nil { - return x.Runtime - } - return "" -} - -func (x *RuncOptions) GetRuntimeRoot() string { - if x != nil { - return x.RuntimeRoot - } - return "" -} - -// Deprecated: Do not use. -func (x *RuncOptions) GetCriuPath() string { - if x != nil { - return x.CriuPath - } - return "" -} - -func (x *RuncOptions) GetSystemdCgroup() bool { - if x != nil { - return x.SystemdCgroup - } - return false -} - -type CreateOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - NoPivotRoot bool `protobuf:"varint,1,opt,name=no_pivot_root,json=noPivotRoot,proto3" json:"no_pivot_root,omitempty"` - OpenTcp bool `protobuf:"varint,2,opt,name=open_tcp,json=openTcp,proto3" json:"open_tcp,omitempty"` - ExternalUnixSockets bool `protobuf:"varint,3,opt,name=external_unix_sockets,json=externalUnixSockets,proto3" json:"external_unix_sockets,omitempty"` - Terminal bool `protobuf:"varint,4,opt,name=terminal,proto3" json:"terminal,omitempty"` - FileLocks bool `protobuf:"varint,5,opt,name=file_locks,json=fileLocks,proto3" json:"file_locks,omitempty"` - EmptyNamespaces []string `protobuf:"bytes,6,rep,name=empty_namespaces,json=emptyNamespaces,proto3" json:"empty_namespaces,omitempty"` - CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"` - NoNewKeyring bool `protobuf:"varint,8,opt,name=no_new_keyring,json=noNewKeyring,proto3" json:"no_new_keyring,omitempty"` - ShimCgroup string `protobuf:"bytes,9,opt,name=shim_cgroup,json=shimCgroup,proto3" json:"shim_cgroup,omitempty"` - IoUid uint32 `protobuf:"varint,10,opt,name=io_uid,json=ioUid,proto3" json:"io_uid,omitempty"` - IoGid uint32 `protobuf:"varint,11,opt,name=io_gid,json=ioGid,proto3" json:"io_gid,omitempty"` - CriuWorkPath string `protobuf:"bytes,12,opt,name=criu_work_path,json=criuWorkPath,proto3" json:"criu_work_path,omitempty"` - CriuImagePath string `protobuf:"bytes,13,opt,name=criu_image_path,json=criuImagePath,proto3" json:"criu_image_path,omitempty"` -} - -func (x *CreateOptions) Reset() { - *x = CreateOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[1] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CreateOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CreateOptions) ProtoMessage() {} - -func (x *CreateOptions) ProtoReflect() protoreflect.Message { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[1] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CreateOptions.ProtoReflect.Descriptor instead. -func (*CreateOptions) Descriptor() ([]byte, []int) { - return file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescGZIP(), []int{1} -} - -func (x *CreateOptions) GetNoPivotRoot() bool { - if x != nil { - return x.NoPivotRoot - } - return false -} - -func (x *CreateOptions) GetOpenTcp() bool { - if x != nil { - return x.OpenTcp - } - return false -} - -func (x *CreateOptions) GetExternalUnixSockets() bool { - if x != nil { - return x.ExternalUnixSockets - } - return false -} - -func (x *CreateOptions) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -func (x *CreateOptions) GetFileLocks() bool { - if x != nil { - return x.FileLocks - } - return false -} - -func (x *CreateOptions) GetEmptyNamespaces() []string { - if x != nil { - return x.EmptyNamespaces - } - return nil -} - -func (x *CreateOptions) GetCgroupsMode() string { - if x != nil { - return x.CgroupsMode - } - return "" -} - -func (x *CreateOptions) GetNoNewKeyring() bool { - if x != nil { - return x.NoNewKeyring - } - return false -} - -func (x *CreateOptions) GetShimCgroup() string { - if x != nil { - return x.ShimCgroup - } - return "" -} - -func (x *CreateOptions) GetIoUid() uint32 { - if x != nil { - return x.IoUid - } - return 0 -} - -func (x *CreateOptions) GetIoGid() uint32 { - if x != nil { - return x.IoGid - } - return 0 -} - -func (x *CreateOptions) GetCriuWorkPath() string { - if x != nil { - return x.CriuWorkPath - } - return "" -} - -func (x *CreateOptions) GetCriuImagePath() string { - if x != nil { - return x.CriuImagePath - } - return "" -} - -type CheckpointOptions struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Exit bool `protobuf:"varint,1,opt,name=exit,proto3" json:"exit,omitempty"` - OpenTcp bool `protobuf:"varint,2,opt,name=open_tcp,json=openTcp,proto3" json:"open_tcp,omitempty"` - ExternalUnixSockets bool `protobuf:"varint,3,opt,name=external_unix_sockets,json=externalUnixSockets,proto3" json:"external_unix_sockets,omitempty"` - Terminal bool `protobuf:"varint,4,opt,name=terminal,proto3" json:"terminal,omitempty"` - FileLocks bool `protobuf:"varint,5,opt,name=file_locks,json=fileLocks,proto3" json:"file_locks,omitempty"` - EmptyNamespaces []string `protobuf:"bytes,6,rep,name=empty_namespaces,json=emptyNamespaces,proto3" json:"empty_namespaces,omitempty"` - CgroupsMode string `protobuf:"bytes,7,opt,name=cgroups_mode,json=cgroupsMode,proto3" json:"cgroups_mode,omitempty"` - WorkPath string `protobuf:"bytes,8,opt,name=work_path,json=workPath,proto3" json:"work_path,omitempty"` - ImagePath string `protobuf:"bytes,9,opt,name=image_path,json=imagePath,proto3" json:"image_path,omitempty"` -} - -func (x *CheckpointOptions) Reset() { - *x = CheckpointOptions{} - if protoimpl.UnsafeEnabled { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[2] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *CheckpointOptions) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*CheckpointOptions) ProtoMessage() {} - -func (x *CheckpointOptions) ProtoReflect() protoreflect.Message { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[2] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use CheckpointOptions.ProtoReflect.Descriptor instead. -func (*CheckpointOptions) Descriptor() ([]byte, []int) { - return file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescGZIP(), []int{2} -} - -func (x *CheckpointOptions) GetExit() bool { - if x != nil { - return x.Exit - } - return false -} - -func (x *CheckpointOptions) GetOpenTcp() bool { - if x != nil { - return x.OpenTcp - } - return false -} - -func (x *CheckpointOptions) GetExternalUnixSockets() bool { - if x != nil { - return x.ExternalUnixSockets - } - return false -} - -func (x *CheckpointOptions) GetTerminal() bool { - if x != nil { - return x.Terminal - } - return false -} - -func (x *CheckpointOptions) GetFileLocks() bool { - if x != nil { - return x.FileLocks - } - return false -} - -func (x *CheckpointOptions) GetEmptyNamespaces() []string { - if x != nil { - return x.EmptyNamespaces - } - return nil -} - -func (x *CheckpointOptions) GetCgroupsMode() string { - if x != nil { - return x.CgroupsMode - } - return "" -} - -func (x *CheckpointOptions) GetWorkPath() string { - if x != nil { - return x.WorkPath - } - return "" -} - -func (x *CheckpointOptions) GetImagePath() string { - if x != nil { - return x.ImagePath - } - return "" -} - -type ProcessDetails struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - ExecID string `protobuf:"bytes,1,opt,name=exec_id,json=execId,proto3" json:"exec_id,omitempty"` -} - -func (x *ProcessDetails) Reset() { - *x = ProcessDetails{} - if protoimpl.UnsafeEnabled { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[3] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *ProcessDetails) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*ProcessDetails) ProtoMessage() {} - -func (x *ProcessDetails) ProtoReflect() protoreflect.Message { - mi := &file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[3] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use ProcessDetails.ProtoReflect.Descriptor instead. -func (*ProcessDetails) Descriptor() ([]byte, []int) { - return file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescGZIP(), []int{3} -} - -func (x *ProcessDetails) GetExecID() string { - if x != nil { - return x.ExecID - } - return "" -} - -var File_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto protoreflect.FileDescriptor - -var file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDesc = []byte{ - 0x0a, 0x43, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, - 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, - 0x72, 0x64, 0x2f, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, - 0x2f, 0x72, 0x75, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x73, 0x2f, 0x72, 0x75, 0x6e, 0x63, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x15, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, - 0x64, 0x2e, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2e, 0x72, 0x75, 0x6e, 0x63, 0x22, 0x92, 0x01, 0x0a, - 0x0b, 0x52, 0x75, 0x6e, 0x63, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x18, 0x0a, 0x07, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x72, - 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, - 0x65, 0x5f, 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x72, 0x75, - 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x1f, 0x0a, 0x09, 0x63, 0x72, 0x69, - 0x75, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x42, 0x02, 0x18, 0x01, - 0x52, 0x08, 0x63, 0x72, 0x69, 0x75, 0x50, 0x61, 0x74, 0x68, 0x12, 0x25, 0x0a, 0x0e, 0x73, 0x79, - 0x73, 0x74, 0x65, 0x6d, 0x64, 0x5f, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0d, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x64, 0x43, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x22, 0xce, 0x03, 0x0a, 0x0d, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x12, 0x22, 0x0a, 0x0d, 0x6e, 0x6f, 0x5f, 0x70, 0x69, 0x76, 0x6f, 0x74, 0x5f, - 0x72, 0x6f, 0x6f, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6e, 0x6f, 0x50, 0x69, - 0x76, 0x6f, 0x74, 0x52, 0x6f, 0x6f, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6f, 0x70, 0x65, 0x6e, 0x5f, - 0x74, 0x63, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x6f, 0x70, 0x65, 0x6e, 0x54, - 0x63, 0x70, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x75, - 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x55, 0x6e, 0x69, 0x78, 0x53, - 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, 0x65, 0x72, 0x6d, 0x69, 0x6e, - 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x5f, 0x6c, 0x6f, 0x63, 0x6b, 0x73, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x6c, 0x65, 0x4c, 0x6f, 0x63, 0x6b, - 0x73, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x73, - 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x6d, 0x70, - 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, - 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0b, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x24, 0x0a, 0x0e, 0x6e, 0x6f, 0x5f, 0x6e, 0x65, 0x77, 0x5f, 0x6b, 0x65, 0x79, 0x72, 0x69, 0x6e, - 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x6e, 0x6f, 0x4e, 0x65, 0x77, 0x4b, 0x65, - 0x79, 0x72, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x73, 0x68, 0x69, 0x6d, 0x5f, 0x63, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x73, 0x68, 0x69, 0x6d, - 0x43, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x12, 0x15, 0x0a, 0x06, 0x69, 0x6f, 0x5f, 0x75, 0x69, 0x64, - 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, 0x6f, 0x55, 0x69, 0x64, 0x12, 0x15, 0x0a, - 0x06, 0x69, 0x6f, 0x5f, 0x67, 0x69, 0x64, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x69, - 0x6f, 0x47, 0x69, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x63, 0x72, 0x69, 0x75, 0x5f, 0x77, 0x6f, 0x72, - 0x6b, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x63, 0x72, - 0x69, 0x75, 0x57, 0x6f, 0x72, 0x6b, 0x50, 0x61, 0x74, 0x68, 0x12, 0x26, 0x0a, 0x0f, 0x63, 0x72, - 0x69, 0x75, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, 0x0d, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0d, 0x63, 0x72, 0x69, 0x75, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x22, 0xbb, 0x02, 0x0a, 0x11, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x4f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x78, 0x69, 0x74, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x65, 0x78, 0x69, 0x74, 0x12, 0x19, 0x0a, 0x08, - 0x6f, 0x70, 0x65, 0x6e, 0x5f, 0x74, 0x63, 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, - 0x6f, 0x70, 0x65, 0x6e, 0x54, 0x63, 0x70, 0x12, 0x32, 0x0a, 0x15, 0x65, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x5f, 0x75, 0x6e, 0x69, 0x78, 0x5f, 0x73, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x13, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, - 0x55, 0x6e, 0x69, 0x78, 0x53, 0x6f, 0x63, 0x6b, 0x65, 0x74, 0x73, 0x12, 0x1a, 0x0a, 0x08, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x74, - 0x65, 0x72, 0x6d, 0x69, 0x6e, 0x61, 0x6c, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x69, 0x6c, 0x65, 0x5f, - 0x6c, 0x6f, 0x63, 0x6b, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x66, 0x69, 0x6c, - 0x65, 0x4c, 0x6f, 0x63, 0x6b, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x5f, - 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x18, 0x06, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x0f, 0x65, 0x6d, 0x70, 0x74, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x73, 0x70, 0x61, 0x63, 0x65, - 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x5f, 0x6d, 0x6f, 0x64, - 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x73, - 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x77, 0x6f, 0x72, 0x6b, 0x5f, 0x70, 0x61, 0x74, - 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x77, 0x6f, 0x72, 0x6b, 0x50, 0x61, 0x74, - 0x68, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x68, 0x18, - 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x22, 0x29, 0x0a, 0x0e, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x44, 0x65, 0x74, 0x61, 0x69, - 0x6c, 0x73, 0x12, 0x17, 0x0a, 0x07, 0x65, 0x78, 0x65, 0x63, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x65, 0x78, 0x65, 0x63, 0x49, 0x64, 0x42, 0x44, 0x5a, 0x42, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, - 0x6e, 0x65, 0x72, 0x64, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x69, 0x6e, 0x65, 0x72, 0x64, 0x2f, - 0x72, 0x75, 0x6e, 0x74, 0x69, 0x6d, 0x65, 0x2f, 0x6c, 0x69, 0x6e, 0x75, 0x78, 0x2f, 0x72, 0x75, - 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, 0x73, 0x3b, 0x72, 0x75, 0x6e, 0x63, 0x74, 0x79, 0x70, 0x65, - 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, -} - -var ( - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescOnce sync.Once - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescData = file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDesc -) - -func file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescGZIP() []byte { - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescOnce.Do(func() { - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescData = protoimpl.X.CompressGZIP(file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescData) - }) - return file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDescData -} - -var file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes = make([]protoimpl.MessageInfo, 4) -var file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_goTypes = []interface{}{ - (*RuncOptions)(nil), // 0: containerd.linux.runc.RuncOptions - (*CreateOptions)(nil), // 1: containerd.linux.runc.CreateOptions - (*CheckpointOptions)(nil), // 2: containerd.linux.runc.CheckpointOptions - (*ProcessDetails)(nil), // 3: containerd.linux.runc.ProcessDetails -} -var file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_depIdxs = []int32{ - 0, // [0:0] is the sub-list for method output_type - 0, // [0:0] is the sub-list for method input_type - 0, // [0:0] is the sub-list for extension type_name - 0, // [0:0] is the sub-list for extension extendee - 0, // [0:0] is the sub-list for field type_name -} - -func init() { file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_init() } -func file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_init() { - if File_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto != nil { - return - } - if !protoimpl.UnsafeEnabled { - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*RuncOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CreateOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*CheckpointOptions); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*ProcessDetails); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - } - type x struct{} - out := protoimpl.TypeBuilder{ - File: protoimpl.DescBuilder{ - GoPackagePath: reflect.TypeOf(x{}).PkgPath(), - RawDescriptor: file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDesc, - NumEnums: 0, - NumMessages: 4, - NumExtensions: 0, - NumServices: 0, - }, - GoTypes: file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_goTypes, - DependencyIndexes: file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_depIdxs, - MessageInfos: file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_msgTypes, - }.Build() - File_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto = out.File - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_rawDesc = nil - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_goTypes = nil - file_github_com_containerd_containerd_runtime_linux_runctypes_runc_proto_depIdxs = nil -} diff --git a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto b/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto deleted file mode 100644 index 5e2d675fbf..0000000000 --- a/vendor/github.com/containerd/containerd/runtime/linux/runctypes/runc.proto +++ /dev/null @@ -1,50 +0,0 @@ -syntax = "proto3"; - -package containerd.linux.runc; - -option go_package = "github.com/containerd/containerd/runtime/linux/runctypes;runctypes"; - -message RuncOptions { - string runtime = 1; - string runtime_root = 2; - // criu binary path. - // - // Deprecated: runc option --criu is now ignored (with a warning), and the - // option will be removed entirely in a future release. Users who need a non- - // standard criu binary should rely on the standard way of looking up binaries - // in $PATH. - string criu_path = 3 [deprecated = true]; - bool systemd_cgroup = 4; -} - -message CreateOptions { - bool no_pivot_root = 1; - bool open_tcp = 2; - bool external_unix_sockets = 3; - bool terminal = 4; - bool file_locks = 5; - repeated string empty_namespaces = 6; - string cgroups_mode = 7; - bool no_new_keyring = 8; - string shim_cgroup = 9; - uint32 io_uid = 10; - uint32 io_gid = 11; - string criu_work_path = 12; - string criu_image_path = 13; -} - -message CheckpointOptions { - bool exit = 1; - bool open_tcp = 2; - bool external_unix_sockets = 3; - bool terminal = 4; - bool file_locks = 5; - repeated string empty_namespaces = 6; - string cgroups_mode = 7; - string work_path = 8; - string image_path = 9; -} - -message ProcessDetails { - string exec_id = 1; -} diff --git a/vendor/github.com/containerd/containerd/services/introspection/introspection.go b/vendor/github.com/containerd/containerd/services/introspection/introspection.go deleted file mode 100644 index c0b54aa684..0000000000 --- a/vendor/github.com/containerd/containerd/services/introspection/introspection.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 introspection - -import ( - context "context" - - "github.com/containerd/log" - - api "github.com/containerd/containerd/api/services/introspection/v1" - "github.com/containerd/containerd/errdefs" - ptypes "github.com/containerd/containerd/protobuf/types" -) - -// Service defines the introspection service interface -type Service interface { - Plugins(context.Context, []string) (*api.PluginsResponse, error) - Server(context.Context, *ptypes.Empty) (*api.ServerResponse, error) -} - -type introspectionRemote struct { - client api.IntrospectionClient -} - -var _ = (Service)(&introspectionRemote{}) - -// NewIntrospectionServiceFromClient creates a new introspection service from an API client -func NewIntrospectionServiceFromClient(c api.IntrospectionClient) Service { - return &introspectionRemote{client: c} -} - -func (i *introspectionRemote) Plugins(ctx context.Context, filters []string) (*api.PluginsResponse, error) { - log.G(ctx).WithField("filters", filters).Debug("remote introspection plugin filters") - resp, err := i.client.Plugins(ctx, &api.PluginsRequest{ - Filters: filters, - }) - - if err != nil { - return nil, errdefs.FromGRPC(err) - } - - return resp, nil -} - -func (i *introspectionRemote) Server(ctx context.Context, in *ptypes.Empty) (*api.ServerResponse, error) { - resp, err := i.client.Server(ctx, in) - - if err != nil { - return nil, errdefs.FromGRPC(err) - } - - return resp, nil -} diff --git a/vendor/github.com/containerd/containerd/services/introspection/local.go b/vendor/github.com/containerd/containerd/services/introspection/local.go deleted file mode 100644 index d3a7dd9c47..0000000000 --- a/vendor/github.com/containerd/containerd/services/introspection/local.go +++ /dev/null @@ -1,292 +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 introspection - -import ( - context "context" - "errors" - "os" - "path/filepath" - "runtime" - "sync" - - "github.com/google/uuid" - "google.golang.org/genproto/googleapis/rpc/code" - rpc "google.golang.org/genproto/googleapis/rpc/status" - "google.golang.org/grpc" - "google.golang.org/grpc/status" - - api "github.com/containerd/containerd/api/services/introspection/v1" - "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/protobuf" - ptypes "github.com/containerd/containerd/protobuf/types" - "github.com/containerd/containerd/services" - "github.com/containerd/containerd/services/warning" -) - -func init() { - plugin.Register(&plugin.Registration{ - Type: plugin.ServicePlugin, - ID: services.IntrospectionService, - Requires: []plugin.Type{plugin.WarningPlugin}, - InitFn: func(ic *plugin.InitContext) (interface{}, error) { - sps, err := ic.GetByType(plugin.WarningPlugin) - if err != nil { - return nil, err - } - p, ok := sps[plugin.DeprecationsPlugin] - if !ok { - return nil, errors.New("warning service not found") - } - - i, err := p.Instance() - if err != nil { - return nil, err - } - - warningClient, ok := i.(warning.Service) - if !ok { - return nil, errors.New("could not create a local client for warning service") - } - - // this service fetches all plugins through the plugin set of the plugin context - return &Local{ - plugins: ic.Plugins(), - root: ic.Root, - warningClient: warningClient, - }, nil - }, - }) -} - -// Local is a local implementation of the introspection service -type Local struct { - mu sync.Mutex - root string - plugins *plugin.Set - pluginCache []*api.Plugin - warningClient warning.Service -} - -var _ = (api.IntrospectionClient)(&Local{}) - -// UpdateLocal updates the local introspection service -func (l *Local) UpdateLocal(root string) { - l.mu.Lock() - defer l.mu.Unlock() - l.root = root -} - -// Plugins returns the locally defined plugins -func (l *Local) Plugins(ctx context.Context, req *api.PluginsRequest, _ ...grpc.CallOption) (*api.PluginsResponse, error) { - filter, err := filters.ParseAll(req.Filters...) - if err != nil { - return nil, errdefs.ToGRPC(err) - } - - var plugins []*api.Plugin - allPlugins := l.getPlugins() - for _, p := range allPlugins { - p := p - if filter.Match(adaptPlugin(p)) { - plugins = append(plugins, p) - } - } - - return &api.PluginsResponse{ - Plugins: plugins, - }, nil -} - -func (l *Local) getPlugins() []*api.Plugin { - l.mu.Lock() - defer l.mu.Unlock() - plugins := l.plugins.GetAll() - if l.pluginCache == nil || len(plugins) != len(l.pluginCache) { - l.pluginCache = pluginsToPB(plugins) - } - return l.pluginCache -} - -// Server returns the local server information -func (l *Local) Server(ctx context.Context, _ *ptypes.Empty, _ ...grpc.CallOption) (*api.ServerResponse, error) { - u, err := l.getUUID() - if err != nil { - return nil, errdefs.ToGRPC(err) - } - pid := os.Getpid() - var pidns uint64 - if runtime.GOOS == "linux" { - pidns, err = statPIDNS(pid) - if err != nil { - return nil, errdefs.ToGRPC(err) - } - } - return &api.ServerResponse{ - UUID: u, - Pid: uint64(pid), - Pidns: pidns, - Deprecations: l.getWarnings(ctx), - }, nil -} - -func (l *Local) PluginInfo(ctx context.Context, in *api.PluginInfoRequest, opts ...grpc.CallOption) (*api.PluginInfoResponse, error) { - return nil, errdefs.ErrNotImplemented -} - -func (l *Local) getUUID() (string, error) { - l.mu.Lock() - defer l.mu.Unlock() - - data, err := os.ReadFile(l.uuidPath()) - if err != nil { - if os.IsNotExist(err) { - return l.generateUUID() - } - return "", err - } - if len(data) == 0 { - return l.generateUUID() - } - u := string(data) - if _, err := uuid.Parse(u); err != nil { - return "", err - } - return u, nil -} - -func (l *Local) generateUUID() (string, error) { - u, err := uuid.NewRandom() - if err != nil { - return "", err - } - path := l.uuidPath() - if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { - return "", err - } - uu := u.String() - if err := os.WriteFile(path, []byte(uu), 0666); err != nil { - return "", err - } - return uu, nil -} - -func (l *Local) uuidPath() string { - return filepath.Join(l.root, "uuid") -} - -func (l *Local) getWarnings(ctx context.Context) []*api.DeprecationWarning { - return warningsPB(ctx, l.warningClient.Warnings()) -} - -func adaptPlugin(o interface{}) filters.Adaptor { - obj := o.(*api.Plugin) - return filters.AdapterFunc(func(fieldpath []string) (string, bool) { - if len(fieldpath) == 0 { - return "", false - } - - switch fieldpath[0] { - case "type": - return obj.Type, len(obj.Type) > 0 - case "id": - return obj.ID, len(obj.ID) > 0 - case "platforms": - // TODO(stevvooe): Another case here where have multiple values. - // May need to refactor the filter system to allow filtering by - // platform, if this is required. - case "capabilities": - // TODO(stevvooe): Need a better way to match against - // collections. We can only return "the value" but really it - // would be best if we could return a set of values for the - // path, any of which could match. - } - - return "", false - }) -} - -func pluginsToPB(plugins []*plugin.Plugin) []*api.Plugin { - var pluginsPB []*api.Plugin - for _, p := range plugins { - var platforms []*types.Platform - for _, p := range p.Meta.Platforms { - platforms = append(platforms, &types.Platform{ - OS: p.OS, - Architecture: p.Architecture, - Variant: p.Variant, - }) - } - - var requires []string - for _, r := range p.Registration.Requires { - requires = append(requires, r.String()) - } - - var initErr *rpc.Status - if err := p.Err(); err != nil { - st, ok := status.FromError(errdefs.ToGRPC(err)) - if ok { - var details []*ptypes.Any - for _, d := range st.Proto().Details { - details = append(details, &ptypes.Any{ - TypeUrl: d.TypeUrl, - Value: d.Value, - }) - } - initErr = &rpc.Status{ - Code: int32(st.Code()), - Message: st.Message(), - Details: details, - } - } else { - initErr = &rpc.Status{ - Code: int32(code.Code_UNKNOWN), - Message: err.Error(), - } - } - } - - pluginsPB = append(pluginsPB, &api.Plugin{ - Type: p.Registration.Type.String(), - ID: p.Registration.ID, - Requires: requires, - Platforms: platforms, - Capabilities: p.Meta.Capabilities, - Exports: p.Meta.Exports, - InitErr: initErr, - }) - } - - return pluginsPB -} - -func warningsPB(ctx context.Context, warnings []warning.Warning) []*api.DeprecationWarning { - var pb []*api.DeprecationWarning - - for _, w := range warnings { - pb = append(pb, &api.DeprecationWarning{ - ID: string(w.ID), - Message: w.Message, - LastOccurrence: protobuf.ToTimestamp(w.LastOccurrence), - }) - } - return pb -} diff --git a/vendor/github.com/containerd/containerd/services/introspection/service.go b/vendor/github.com/containerd/containerd/services/introspection/service.go deleted file mode 100644 index 71b24aa7dc..0000000000 --- a/vendor/github.com/containerd/containerd/services/introspection/service.go +++ /dev/null @@ -1,87 +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 introspection - -import ( - context "context" - "errors" - - "google.golang.org/grpc" - - api "github.com/containerd/containerd/api/services/introspection/v1" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/plugin" - ptypes "github.com/containerd/containerd/protobuf/types" - "github.com/containerd/containerd/services" -) - -func init() { - plugin.Register(&plugin.Registration{ - Type: plugin.GRPCPlugin, - ID: "introspection", - Requires: []plugin.Type{plugin.ServicePlugin}, - InitFn: func(ic *plugin.InitContext) (interface{}, error) { - plugins, err := ic.GetByType(plugin.ServicePlugin) - if err != nil { - return nil, err - } - p, ok := plugins[services.IntrospectionService] - if !ok { - return nil, errors.New("introspection service not found") - } - - i, err := p.Instance() - if err != nil { - return nil, err - } - - localClient, ok := i.(*Local) - if !ok { - return nil, errors.New("could not create a local client for introspection service") - } - localClient.UpdateLocal(ic.Root) - - return &server{ - local: localClient, - }, nil - }, - }) -} - -type server struct { - local api.IntrospectionClient - api.UnimplementedIntrospectionServer -} - -var _ = (api.IntrospectionServer)(&server{}) - -func (s *server) Register(server *grpc.Server) error { - api.RegisterIntrospectionServer(server, s) - return nil -} - -func (s *server) Plugins(ctx context.Context, req *api.PluginsRequest) (*api.PluginsResponse, error) { - return s.local.Plugins(ctx, req) -} - -func (s *server) Server(ctx context.Context, empty *ptypes.Empty) (*api.ServerResponse, error) { - return s.local.Server(ctx, empty) -} - -func (s *server) PluginInfo(ctx context.Context, in *api.PluginInfoRequest) (*api.PluginInfoResponse, error) { - return nil, errdefs.ToGRPC(errdefs.ErrNotImplemented) -} diff --git a/vendor/github.com/containerd/containerd/services/warning/service.go b/vendor/github.com/containerd/containerd/services/warning/service.go deleted file mode 100644 index 9bc288ba5a..0000000000 --- a/vendor/github.com/containerd/containerd/services/warning/service.go +++ /dev/null @@ -1,83 +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 warning - -import ( - "context" - "sync" - "time" - - "github.com/containerd/log" - - deprecation "github.com/containerd/containerd/pkg/deprecation" - "github.com/containerd/containerd/plugin" -) - -type Service interface { - Emit(context.Context, deprecation.Warning) - Warnings() []Warning -} - -func init() { - plugin.Register(&plugin.Registration{ - Type: plugin.WarningPlugin, - ID: plugin.DeprecationsPlugin, - InitFn: func(ic *plugin.InitContext) (interface{}, error) { - return &service{warnings: make(map[deprecation.Warning]time.Time)}, nil - }, - }) -} - -type Warning struct { - ID deprecation.Warning - LastOccurrence time.Time - Message string -} - -var _ Service = (*service)(nil) - -type service struct { - warnings map[deprecation.Warning]time.Time - m sync.RWMutex -} - -func (s *service) Emit(ctx context.Context, warning deprecation.Warning) { - if !deprecation.Valid(warning) { - log.G(ctx).WithField("warningID", string(warning)).Warn("invalid deprecation warning") - return - } - s.m.Lock() - defer s.m.Unlock() - s.warnings[warning] = time.Now() -} -func (s *service) Warnings() []Warning { - s.m.RLock() - defer s.m.RUnlock() - var warnings []Warning - for k, v := range s.warnings { - msg, ok := deprecation.Message(k) - if !ok { - continue - } - warnings = append(warnings, Warning{ - ID: k, - LastOccurrence: v, - Message: msg, - }) - } - return warnings -} diff --git a/vendor/github.com/containerd/containerd/task_opts_unix.go b/vendor/github.com/containerd/containerd/task_opts_unix.go deleted file mode 100644 index f1f1b01be1..0000000000 --- a/vendor/github.com/containerd/containerd/task_opts_unix.go +++ /dev/null @@ -1,157 +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 containerd - -import ( - "context" - "errors" - - "github.com/containerd/containerd/api/types/runc/options" - "github.com/containerd/containerd/runtime/linux/runctypes" -) - -// WithNoNewKeyring causes tasks not to be created with a new keyring for secret storage. -// There is an upper limit on the number of keyrings in a linux system -func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error { - if CheckRuntime(ti.Runtime(), "io.containerd.runc") { - if ti.Options == nil { - ti.Options = &options.Options{} - } - opts, ok := ti.Options.(*options.Options) - if !ok { - return errors.New("invalid v2 shim create options format") - } - opts.NoNewKeyring = true - } else { - if ti.Options == nil { - ti.Options = &runctypes.CreateOptions{} - } - opts, ok := ti.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("could not cast TaskInfo Options to CreateOptions") - } - opts.NoNewKeyring = true - } - return nil -} - -// WithNoPivotRoot instructs the runtime not to you pivot_root -func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error { - if CheckRuntime(ti.Runtime(), "io.containerd.runc") { - if ti.Options == nil { - ti.Options = &options.Options{} - } - opts, ok := ti.Options.(*options.Options) - if !ok { - return errors.New("invalid v2 shim create options format") - } - opts.NoPivotRoot = true - } else { - if ti.Options == nil { - ti.Options = &runctypes.CreateOptions{ - NoPivotRoot: true, - } - return nil - } - opts, ok := ti.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("invalid options type, expected runctypes.CreateOptions") - } - opts.NoPivotRoot = true - } - return nil -} - -// WithShimCgroup sets the existing cgroup for the shim -func WithShimCgroup(path string) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { - if CheckRuntime(ti.Runtime(), "io.containerd.runc") { - if ti.Options == nil { - ti.Options = &options.Options{} - } - opts, ok := ti.Options.(*options.Options) - if !ok { - return errors.New("invalid v2 shim create options format") - } - opts.ShimCgroup = path - } else { - if ti.Options == nil { - ti.Options = &runctypes.CreateOptions{} - } - opts, ok := ti.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("could not cast TaskInfo Options to CreateOptions") - } - opts.ShimCgroup = path - } - return nil - } -} - -// WithUIDOwner allows console I/O to work with the remapped UID in user namespace -func WithUIDOwner(uid uint32) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { - if CheckRuntime(ti.Runtime(), "io.containerd.runc") { - if ti.Options == nil { - ti.Options = &options.Options{} - } - opts, ok := ti.Options.(*options.Options) - if !ok { - return errors.New("invalid v2 shim create options format") - } - opts.IoUid = uid - } else { - if ti.Options == nil { - ti.Options = &runctypes.CreateOptions{} - } - opts, ok := ti.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("could not cast TaskInfo Options to CreateOptions") - } - opts.IoUid = uid - } - return nil - } -} - -// WithGIDOwner allows console I/O to work with the remapped GID in user namespace -func WithGIDOwner(gid uint32) NewTaskOpts { - return func(ctx context.Context, c *Client, ti *TaskInfo) error { - if CheckRuntime(ti.Runtime(), "io.containerd.runc") { - if ti.Options == nil { - ti.Options = &options.Options{} - } - opts, ok := ti.Options.(*options.Options) - if !ok { - return errors.New("invalid v2 shim create options format") - } - opts.IoGid = gid - } else { - if ti.Options == nil { - ti.Options = &runctypes.CreateOptions{} - } - opts, ok := ti.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("could not cast TaskInfo Options to CreateOptions") - } - opts.IoGid = gid - } - return nil - } -} diff --git a/vendor/github.com/containerd/containerd/LICENSE b/vendor/github.com/containerd/containerd/v2/LICENSE similarity index 100% rename from vendor/github.com/containerd/containerd/LICENSE rename to vendor/github.com/containerd/containerd/v2/LICENSE diff --git a/vendor/github.com/containerd/containerd/NOTICE b/vendor/github.com/containerd/containerd/v2/NOTICE similarity index 100% rename from vendor/github.com/containerd/containerd/NOTICE rename to vendor/github.com/containerd/containerd/v2/NOTICE diff --git a/vendor/github.com/containerd/containerd/client.go b/vendor/github.com/containerd/containerd/v2/client/client.go similarity index 78% rename from vendor/github.com/containerd/containerd/client.go rename to vendor/github.com/containerd/containerd/v2/client/client.go index 69614712ec..c58459b214 100644 --- a/vendor/github.com/containerd/containerd/client.go +++ b/vendor/github.com/containerd/containerd/v2/client/client.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "bytes" @@ -27,22 +27,11 @@ import ( "sync" "time" - "github.com/containerd/platforms" - "github.com/containerd/typeurl/v2" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/opencontainers/runtime-spec/specs-go" - "golang.org/x/sync/semaphore" - "google.golang.org/grpc" - "google.golang.org/grpc/backoff" - "google.golang.org/grpc/credentials/insecure" - "google.golang.org/grpc/health/grpc_health_v1" + "google.golang.org/grpc/resolver" containersapi "github.com/containerd/containerd/api/services/containers/v1" - contentapi "github.com/containerd/containerd/api/services/content/v1" diffapi "github.com/containerd/containerd/api/services/diff/v1" - eventsapi "github.com/containerd/containerd/api/services/events/v1" imagesapi "github.com/containerd/containerd/api/services/images/v1" - introspectionapi "github.com/containerd/containerd/api/services/introspection/v1" leasesapi "github.com/containerd/containerd/api/services/leases/v1" namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1" sandboxsapi "github.com/containerd/containerd/api/services/sandbox/v1" @@ -50,26 +39,39 @@ import ( "github.com/containerd/containerd/api/services/tasks/v1" versionservice "github.com/containerd/containerd/api/services/version/v1" apitypes "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - contentproxy "github.com/containerd/containerd/content/proxy" - "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/events" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - leasesproxy "github.com/containerd/containerd/leases/proxy" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/pkg/dialer" - "github.com/containerd/containerd/plugin" - ptypes "github.com/containerd/containerd/protobuf/types" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/sandbox" - sandboxproxy "github.com/containerd/containerd/sandbox/proxy" - "github.com/containerd/containerd/services/introspection" - "github.com/containerd/containerd/snapshots" - snproxy "github.com/containerd/containerd/snapshots/proxy" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/content" + contentproxy "github.com/containerd/containerd/v2/core/content/proxy" + "github.com/containerd/containerd/v2/core/events" + eventsproxy "github.com/containerd/containerd/v2/core/events/proxy" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/introspection" + introspectionproxy "github.com/containerd/containerd/v2/core/introspection/proxy" + "github.com/containerd/containerd/v2/core/leases" + leasesproxy "github.com/containerd/containerd/v2/core/leases/proxy" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/sandbox" + sandboxproxy "github.com/containerd/containerd/v2/core/sandbox/proxy" + "github.com/containerd/containerd/v2/core/snapshots" + snproxy "github.com/containerd/containerd/v2/core/snapshots/proxy" + "github.com/containerd/containerd/v2/defaults" + "github.com/containerd/containerd/v2/pkg/dialer" + "github.com/containerd/containerd/v2/pkg/namespaces" + ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/containerd/v2/plugins" + "github.com/containerd/errdefs" + "github.com/containerd/platforms" + "github.com/containerd/typeurl/v2" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/opencontainers/runtime-spec/specs-go" + "github.com/opencontainers/runtime-spec/specs-go/features" + "golang.org/x/sync/semaphore" + "google.golang.org/grpc" + "google.golang.org/grpc/backoff" + "google.golang.org/grpc/credentials/insecure" + "google.golang.org/grpc/health/grpc_health_v1" ) func init() { @@ -80,11 +82,20 @@ func init() { typeurl.Register(&specs.Process{}, prefix, "opencontainers/runtime-spec", major, "Process") typeurl.Register(&specs.LinuxResources{}, prefix, "opencontainers/runtime-spec", major, "LinuxResources") typeurl.Register(&specs.WindowsResources{}, prefix, "opencontainers/runtime-spec", major, "WindowsResources") + typeurl.Register(&features.Features{}, prefix, "opencontainers/runtime-spec", major, "features", "Features") + + if runtime.GOOS == "windows" { + // After bumping GRPC to 1.64, Windows tests started failing with: "name resolver error: produced zero addresses". + // This is happening because grpc.NewClient uses DNS resolver by default, which apparently not what we want + // when using socket paths on Windows. + // Using a workaround from https://github.com/grpc/grpc-go/issues/1786#issuecomment-2119088770 + resolver.SetDefaultScheme("passthrough") + } } // New returns a new containerd client that is connected to the containerd // instance provided by address -func New(address string, opts ...ClientOpt) (*Client, error) { +func New(address string, opts ...Opt) (*Client, error) { var copts clientOpts for _, o := range opts { if err := o(&copts); err != nil { @@ -116,17 +127,14 @@ func New(address string, opts ...ClientOpt) (*Client, error) { } if address != "" { backoffConfig := backoff.DefaultConfig - backoffConfig.MaxDelay = 3 * time.Second + backoffConfig.MaxDelay = copts.timeout connParams := grpc.ConnectParams{ Backoff: backoffConfig, } gopts := []grpc.DialOption{ - grpc.WithBlock(), grpc.WithTransportCredentials(insecure.NewCredentials()), - grpc.FailOnNonTempDialError(true), grpc.WithConnectParams(connParams), grpc.WithContextDialer(dialer.ContextDialer), - grpc.WithReturnConnectionError(), } if len(copts.dialOptions) > 0 { gopts = copts.dialOptions @@ -144,9 +152,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) { } connector := func() (*grpc.ClientConn, error) { - ctx, cancel := context.WithTimeout(context.Background(), copts.timeout) - defer cancel() - conn, err := grpc.DialContext(ctx, dialer.DialAddress(address), gopts...) + conn, err := grpc.NewClient(dialer.DialAddress(address), gopts...) if err != nil { return nil, fmt.Errorf("failed to dial %q: %w", address, err) } @@ -176,7 +182,7 @@ func New(address string, opts ...ClientOpt) (*Client, error) { // NewWithConn returns a new containerd client that is connected to the containerd // instance provided by the connection -func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) { +func NewWithConn(conn *grpc.ClientConn, opts ...Opt) (*Client, error) { var copts clientOpts for _, o := range opts { if err := o(&copts); err != nil { @@ -186,7 +192,7 @@ func NewWithConn(conn *grpc.ClientConn, opts ...ClientOpt) (*Client, error) { c := &Client{ defaultns: copts.defaultns, conn: conn, - runtime: fmt.Sprintf("%s.%s", plugin.RuntimePlugin, runtime.GOOS), + runtime: defaults.DefaultRuntime, } if copts.defaultPlatform != nil { @@ -269,9 +275,9 @@ func (c *Client) Containers(ctx context.Context, filters ...string) ([]Container if err != nil { return nil, err } - var out []Container - for _, container := range r { - out = append(out, containerFromRecord(c, container)) + out := make([]Container, len(r)) + for i, container := range r { + out[i] = containerFromRecord(c, container) } return out, nil } @@ -279,6 +285,8 @@ func (c *Client) Containers(ctx context.Context, filters ...string) ([]Container // NewContainer will create a new container with the provided id. // The id must be unique within the namespace. func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) { + ctx, span := tracing.StartSpan(ctx, "client.NewContainer") + defer span.End() ctx, done, err := c.WithLease(ctx) if err != nil { return nil, err @@ -296,6 +304,13 @@ func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContain return nil, err } } + + span.SetAttributes( + tracing.Attribute("container.id", container.ID), + tracing.Attribute("container.image.ref", container.Image), + tracing.Attribute("container.runtime.name", container.Runtime.Name), + tracing.Attribute("container.snapshotter.name", container.Snapshotter), + ) r, err := c.ContainerService().Create(ctx, container) if err != nil { return nil, err @@ -305,10 +320,21 @@ func (c *Client) NewContainer(ctx context.Context, id string, opts ...NewContain // LoadContainer loads an existing container from metadata func (c *Client) LoadContainer(ctx context.Context, id string) (Container, error) { + ctx, span := tracing.StartSpan(ctx, "client.LoadContainer") + defer span.End() r, err := c.ContainerService().Get(ctx, id) if err != nil { return nil, err } + + span.SetAttributes( + tracing.Attribute("container.id", r.ID), + tracing.Attribute("container.image.ref", r.Image), + tracing.Attribute("container.runtime.name", r.Runtime.Name), + tracing.Attribute("container.snapshotter.name", r.Snapshotter), + tracing.Attribute("container.createdAt", r.CreatedAt.Format(time.RFC3339)), + tracing.Attribute("container.updatedAt", r.UpdatedAt.Format(time.RFC3339)), + ) return containerFromRecord(c, r), nil } @@ -404,13 +430,9 @@ func (c *Client) Fetch(ctx context.Context, ref string, opts ...RemoteOpt) (imag if len(fetchCtx.Platforms) == 0 { fetchCtx.PlatformMatcher = platforms.All } else { - var ps []ocispec.Platform - for _, s := range fetchCtx.Platforms { - p, err := platforms.Parse(s) - if err != nil { - return images.Image{}, fmt.Errorf("invalid platform %s: %w", s, err) - } - ps = append(ps, p) + ps, err := platforms.ParseAll(fetchCtx.Platforms) + if err != nil { + return images.Image{}, err } fetchCtx.PlatformMatcher = platforms.Any(ps...) @@ -440,13 +462,9 @@ func (c *Client) Push(ctx context.Context, ref string, desc ocispec.Descriptor, } if pushCtx.PlatformMatcher == nil { if len(pushCtx.Platforms) > 0 { - var ps []ocispec.Platform - for _, platform := range pushCtx.Platforms { - p, err := platforms.Parse(platform) - if err != nil { - return fmt.Errorf("invalid platform %s: %w", platform, err) - } - ps = append(ps, p) + ps, err := platforms.ParseAll(pushCtx.Platforms) + if err != nil { + return err } pushCtx.PlatformMatcher = platforms.Any(ps...) } else { @@ -522,9 +540,9 @@ func (c *Client) Restore(ctx context.Context, id string, checkpoint Image, opts } defer done(ctx) - copts := []NewContainerOpts{} - for _, o := range opts { - copts = append(copts, o(ctx, id, c, checkpoint, index)) + copts := make([]NewContainerOpts, len(opts)) + for i, o := range opts { + copts[i] = o(ctx, id, c, checkpoint, index) } ctr, err := c.NewContainer(ctx, id, copts...) @@ -547,6 +565,19 @@ func writeIndex(ctx context.Context, index *ocispec.Index, client *Client, ref s return writeContent(ctx, client.ContentStore(), ocispec.MediaTypeImageIndex, ref, bytes.NewReader(data), content.WithLabels(labels)) } +func decodeIndex(ctx context.Context, store content.Provider, desc ocispec.Descriptor) (*ocispec.Index, error) { + var index ocispec.Index + p, err := content.ReadBlob(ctx, store, desc) + if err != nil { + return nil, err + } + if err := json.Unmarshal(p, &index); err != nil { + return nil, err + } + + return &index, nil +} + // GetLabel gets a label value from namespace store // If there is no default label, an empty string returned with nil error func (c *Client) GetLabel(ctx context.Context, label string) (string, error) { @@ -616,14 +647,14 @@ func (c *Client) ContentStore() content.Store { } c.connMu.Lock() defer c.connMu.Unlock() - return contentproxy.NewContentStore(contentapi.NewContentClient(c.conn)) + return contentproxy.NewContentStore(c.conn) } // SnapshotService returns the underlying snapshotter for the provided snapshotter name func (c *Client) SnapshotService(snapshotterName string) snapshots.Snapshotter { snapshotterName, err := c.resolveSnapshotterName(context.Background(), snapshotterName) if err != nil { - snapshotterName = DefaultSnapshotter + snapshotterName = defaults.DefaultSnapshotter } if c.snapshotters != nil { return c.snapshotters[snapshotterName] @@ -675,7 +706,7 @@ func (c *Client) IntrospectionService() introspection.Service { } c.connMu.Lock() defer c.connMu.Unlock() - return introspection.NewIntrospectionServiceFromClient(introspectionapi.NewIntrospectionClient(c.conn)) + return introspectionproxy.NewIntrospectionProxy(c.conn) } // LeasesService returns the underlying Leases Client @@ -702,7 +733,7 @@ func (c *Client) EventService() EventService { } c.connMu.Lock() defer c.connMu.Unlock() - return NewEventServiceFromClient(eventsapi.NewEventsClient(c.conn)) + return eventsproxy.NewRemoteEvents(c.conn) } // SandboxStore returns the underlying sandbox store client @@ -716,13 +747,13 @@ func (c *Client) SandboxStore() sandbox.Store { } // SandboxController returns the underlying sandbox controller client -func (c *Client) SandboxController() sandbox.Controller { - if c.sandboxController != nil { - return c.sandboxController +func (c *Client) SandboxController(name string) sandbox.Controller { + if c.sandboxers != nil { + return c.sandboxers[name] } c.connMu.Lock() defer c.connMu.Unlock() - return sandboxproxy.NewSandboxController(sandboxsapi.NewControllerClient(c.conn)) + return sandboxproxy.NewSandboxController(sandboxsapi.NewControllerClient(c.conn), name) } // VersionService returns the underlying VersionClient @@ -732,8 +763,9 @@ func (c *Client) VersionService() versionservice.VersionClient { return versionservice.NewVersionClient(c.conn) } -// Conn returns the underlying GRPC connection object -func (c *Client) Conn() *grpc.ClientConn { +// Conn returns the underlying RPC connection object +// Either *grpc.ClientConn or *ttrpc.Conn +func (c *Client) Conn() any { c.connMu.Lock() defer c.connMu.Unlock() return c.conn @@ -779,7 +811,7 @@ func (c *Client) Server(ctx context.Context) (ServerInfo, error) { } c.connMu.Unlock() - response, err := c.IntrospectionService().Server(ctx, &ptypes.Empty{}) + response, err := c.IntrospectionService().Server(ctx) if err != nil { return ServerInfo{}, err } @@ -798,7 +830,7 @@ func (c *Client) resolveSnapshotterName(ctx context.Context, name string) (strin if label != "" { name = label } else { - name = DefaultSnapshotter + name = defaults.DefaultSnapshotter } } @@ -819,30 +851,13 @@ func (c *Client) getSnapshotter(ctx context.Context, name string) (snapshots.Sna return s, nil } -// CheckRuntime returns true if the current runtime matches the expected -// runtime. Providing various parts of the runtime schema will match those -// parts of the expected runtime -func CheckRuntime(current, expected string) bool { - cp := strings.Split(current, ".") - l := len(cp) - for i, p := range strings.Split(expected, ".") { - if i > l { - return false - } - if p != cp[i] { - return false - } - } - return true -} - // GetSnapshotterSupportedPlatforms returns a platform matchers which represents the // supported platforms for the given snapshotters func (c *Client) GetSnapshotterSupportedPlatforms(ctx context.Context, snapshotterName string) (platforms.MatchComparer, error) { - filters := []string{fmt.Sprintf("type==%s, id==%s", plugin.SnapshotPlugin, snapshotterName)} + filters := []string{fmt.Sprintf("type==%s, id==%s", plugins.SnapshotPlugin, snapshotterName)} in := c.IntrospectionService() - resp, err := in.Plugins(ctx, filters) + resp, err := in.Plugins(ctx, filters...) if err != nil { return nil, err } @@ -870,10 +885,10 @@ func toPlatforms(pt []*apitypes.Platform) []ocispec.Platform { // GetSnapshotterCapabilities returns the capabilities of a snapshotter. func (c *Client) GetSnapshotterCapabilities(ctx context.Context, snapshotterName string) ([]string, error) { - filters := []string{fmt.Sprintf("type==%s, id==%s", plugin.SnapshotPlugin, snapshotterName)} + filters := []string{fmt.Sprintf("type==%s, id==%s", plugins.SnapshotPlugin, snapshotterName)} in := c.IntrospectionService() - resp, err := in.Plugins(ctx, filters) + resp, err := in.Plugins(ctx, filters...) if err != nil { return nil, err } @@ -885,3 +900,66 @@ func (c *Client) GetSnapshotterCapabilities(ctx context.Context, snapshotterName sn := resp.Plugins[0] return sn.Capabilities, nil } + +type RuntimeVersion struct { + Version string + Revision string +} + +type RuntimeInfo struct { + Name string + Version RuntimeVersion + Options interface{} + Features interface{} + Annotations map[string]string +} + +func (c *Client) RuntimeInfo(ctx context.Context, runtimePath string, runtimeOptions interface{}) (*RuntimeInfo, error) { + rt := c.runtime + if runtimePath != "" { + rt = runtimePath + } + rr := &apitypes.RuntimeRequest{ + RuntimePath: rt, + } + var err error + if runtimeOptions != nil { + rr.Options, err = typeurl.MarshalAnyToProto(runtimeOptions) + if err != nil { + return nil, fmt.Errorf("failed to marshal %T: %w", runtimeOptions, err) + } + } + + s := c.IntrospectionService() + + resp, err := s.PluginInfo(ctx, string(plugins.RuntimePluginV2), "task", rr) + if err != nil { + return nil, err + } + + var info apitypes.RuntimeInfo + if err := typeurl.UnmarshalTo(resp.Extra, &info); err != nil { + return nil, fmt.Errorf("failed to get runtime info from plugin info: %w", err) + } + + var result RuntimeInfo + result.Name = info.Name + if info.Version != nil { + result.Version.Version = info.Version.Version + result.Version.Revision = info.Version.Revision + } + if info.Options != nil { + result.Options, err = typeurl.UnmarshalAny(info.Options) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal RuntimeInfo.Options (%T): %w", info.Options, err) + } + } + if info.Features != nil { + result.Features, err = typeurl.UnmarshalAny(info.Features) + if err != nil { + return nil, fmt.Errorf("failed to unmarshal RuntimeInfo.Features (%T): %w", info.Features, err) + } + } + result.Annotations = info.Annotations + return &result, nil +} diff --git a/vendor/github.com/containerd/containerd/client_opts.go b/vendor/github.com/containerd/containerd/v2/client/client_opts.go similarity index 89% rename from vendor/github.com/containerd/containerd/client_opts.go rename to vendor/github.com/containerd/containerd/v2/client/client_opts.go index 7fa16a5f9b..54b37d4ca3 100644 --- a/vendor/github.com/containerd/containerd/client_opts.go +++ b/vendor/github.com/containerd/containerd/v2/client/client_opts.go @@ -14,14 +14,14 @@ limitations under the License. */ -package containerd +package client import ( "time" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -38,14 +38,14 @@ type clientOpts struct { timeout time.Duration } -// ClientOpt allows callers to set options on the containerd client -type ClientOpt func(c *clientOpts) error +// Opt allows callers to set options on the containerd client +type Opt func(c *clientOpts) error // WithDefaultNamespace sets the default namespace on the client // // Any operation that does not have a namespace set on the context will // be provided the default namespace -func WithDefaultNamespace(ns string) ClientOpt { +func WithDefaultNamespace(ns string) Opt { return func(c *clientOpts) error { c.defaultns = ns return nil @@ -53,7 +53,7 @@ func WithDefaultNamespace(ns string) ClientOpt { } // WithDefaultRuntime sets the default runtime on the client -func WithDefaultRuntime(rt string) ClientOpt { +func WithDefaultRuntime(rt string) Opt { return func(c *clientOpts) error { c.defaultRuntime = rt return nil @@ -61,7 +61,7 @@ func WithDefaultRuntime(rt string) ClientOpt { } // WithDefaultPlatform sets the default platform matcher on the client -func WithDefaultPlatform(platform platforms.MatchComparer) ClientOpt { +func WithDefaultPlatform(platform platforms.MatchComparer) Opt { return func(c *clientOpts) error { c.defaultPlatform = platform return nil @@ -69,7 +69,7 @@ func WithDefaultPlatform(platform platforms.MatchComparer) ClientOpt { } // WithDialOpts allows grpc.DialOptions to be set on the connection -func WithDialOpts(opts []grpc.DialOption) ClientOpt { +func WithDialOpts(opts []grpc.DialOption) Opt { return func(c *clientOpts) error { c.dialOptions = opts return nil @@ -77,7 +77,7 @@ func WithDialOpts(opts []grpc.DialOption) ClientOpt { } // WithCallOpts allows grpc.CallOptions to be set on the connection -func WithCallOpts(opts []grpc.CallOption) ClientOpt { +func WithCallOpts(opts []grpc.CallOption) Opt { return func(c *clientOpts) error { c.callOptions = opts return nil @@ -85,7 +85,7 @@ func WithCallOpts(opts []grpc.CallOption) ClientOpt { } // WithServices sets services used by the client. -func WithServices(opts ...ServicesOpt) ClientOpt { +func WithServices(opts ...ServicesOpt) Opt { return func(c *clientOpts) error { c.services = &services{} for _, o := range opts { @@ -96,7 +96,7 @@ func WithServices(opts ...ServicesOpt) ClientOpt { } // WithTimeout sets the connection timeout for the client -func WithTimeout(d time.Duration) ClientOpt { +func WithTimeout(d time.Duration) Opt { return func(c *clientOpts) error { c.timeout = d return nil @@ -110,7 +110,7 @@ type RemoteOpt func(*Client, *RemoteContext) error // content for func WithPlatform(platform string) RemoteOpt { if platform == "" { - platform = platforms.Format(platforms.DefaultSpec()) // For 1.7 continue using the old format without os-version included. + platform = platforms.DefaultString() } return func(_ *Client, c *RemoteContext) error { for _, p := range c.Platforms { diff --git a/vendor/github.com/containerd/containerd/container.go b/vendor/github.com/containerd/containerd/v2/client/container.go similarity index 86% rename from vendor/github.com/containerd/containerd/container.go rename to vendor/github.com/containerd/containerd/v2/client/container.go index d8ff21bc73..b9cf25e937 100644 --- a/vendor/github.com/containerd/containerd/container.go +++ b/vendor/github.com/containerd/containerd/v2/client/container.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -28,21 +28,22 @@ import ( "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types/runc/options" tasktypes "github.com/containerd/containerd/api/types/task" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/protobuf" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" "github.com/containerd/fifo" "github.com/containerd/typeurl/v2" ver "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/selinux/go-selinux/label" + + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/tracing" ) const ( - checkpointImageNameLabel = "org.opencontainers.image.ref.name" checkpointRuntimeNameLabel = "io.containerd.checkpoint.runtime" checkpointSnapshotterNameLabel = "io.containerd.checkpoint.snapshotter" ) @@ -61,8 +62,13 @@ type Container interface { Spec(context.Context) (*oci.Spec, error) // Task returns the current task for the container // + // If cio.Load options are passed the client will Load the IO for the running + // task. + // // If cio.Attach options are passed the client will reattach to the IO for the running - // task. If no task exists for the container a NotFound error is returned + // task. + // + // If no task exists for the container a NotFound error is returned // // Clients must make sure that only one reader is attached to the task and consuming // the output from the task's fifos @@ -137,6 +143,10 @@ func (c *container) Labels(ctx context.Context) (map[string]string, error) { } func (c *container) SetLabels(ctx context.Context, labels map[string]string) (map[string]string, error) { + ctx, span := tracing.StartSpan(ctx, "container.SetLabels", + tracing.WithAttribute("container.id", c.id), + ) + defer span.End() container := containers.Container{ ID: c.id, Labels: labels, @@ -172,6 +182,10 @@ func (c *container) Spec(ctx context.Context) (*oci.Spec, error) { // Delete deletes an existing container // an error is returned if the container has running tasks func (c *container) Delete(ctx context.Context, opts ...DeleteOpts) error { + ctx, span := tracing.StartSpan(ctx, "container.Delete", + tracing.WithAttribute("container.id", c.id), + ) + defer span.End() if _, err := c.loadTask(ctx, nil); err == nil { return fmt.Errorf("cannot delete running task %v: %w", c.id, errdefs.ErrFailedPrecondition) } @@ -208,6 +222,8 @@ func (c *container) Image(ctx context.Context) (Image, error) { } func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...NewTaskOpts) (_ Task, err error) { + ctx, span := tracing.StartSpan(ctx, "container.NewTask") + defer span.End() i, err := ioCreate(c.id) if err != nil { return nil, err @@ -250,9 +266,8 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N } for _, m := range mounts { if spec.Linux != nil && spec.Linux.MountLabel != "" { - context := label.FormatMountLabel("", spec.Linux.MountLabel) - if context != "" { - m.Options = append(m.Options, context) + if ml := label.FormatMountLabel("", spec.Linux.MountLabel); ml != "" { + m.Options = append(m.Options, ml) } } request.Rootfs = append(request.Rootfs, &types.Mount{ @@ -271,23 +286,21 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N return nil, err } } - if info.RootFS != nil { - for _, m := range info.RootFS { - request.Rootfs = append(request.Rootfs, &types.Mount{ - Type: m.Type, - Source: m.Source, - Target: m.Target, - Options: m.Options, - }) - } + for _, m := range info.RootFS { + request.Rootfs = append(request.Rootfs, &types.Mount{ + Type: m.Type, + Source: m.Source, + Target: m.Target, + Options: m.Options, + }) } request.RuntimePath = info.RuntimePath if info.Options != nil { - any, err := typeurl.MarshalAny(info.Options) + o, err := typeurl.MarshalAny(info.Options) if err != nil { return nil, err } - request.Options = protobuf.FromAny(any) + request.Options = typeurl.MarshalProto(o) } t := &task{ client: c.client, @@ -298,16 +311,28 @@ func (c *container) NewTask(ctx context.Context, ioCreate cio.Creator, opts ...N if info.Checkpoint != nil { request.Checkpoint = info.Checkpoint } + + span.SetAttributes( + tracing.Attribute("task.container.id", request.ContainerID), + tracing.Attribute("task.request.options", request.Options.String()), + tracing.Attribute("task.runtime.name", info.runtime), + ) response, err := c.client.TaskService().Create(ctx, request) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } + + span.AddEvent("task created", + tracing.Attribute("task.process.id", int(response.Pid)), + ) t.pid = response.Pid return t, nil } func (c *container) Update(ctx context.Context, opts ...UpdateContainerOpts) error { // fetch the current container config before updating it + ctx, span := tracing.StartSpan(ctx, "container.Update") + defer span.End() r, err := c.get(ctx) if err != nil { return err @@ -318,7 +343,7 @@ func (c *container) Update(ctx context.Context, opts ...UpdateContainerOpts) err } } if _, err := c.client.ContainerService().Update(ctx, r); err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } @@ -355,7 +380,7 @@ func (c *container) Checkpoint(ctx context.Context, ref string, opts ...Checkpoi defer done(ctx) // add image name to manifest - index.Annotations[checkpointImageNameLabel] = img.Name() + index.Annotations[ocispec.AnnotationRefName] = img.Name() // add runtime info to index index.Annotations[checkpointRuntimeNameLabel] = info.Runtime.Name // add snapshotter info to index @@ -364,7 +389,7 @@ func (c *container) Checkpoint(ctx context.Context, ref string, opts ...Checkpoi // process remaining opts for _, o := range opts { if err := o(ctx, c.client, &info, index, copts); err != nil { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) if !errdefs.IsAlreadyExists(err) { return nil, err } @@ -392,7 +417,7 @@ func (c *container) loadTask(ctx context.Context, ioAttach cio.Attach) (Task, er ContainerID: c.id, }) if err != nil { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) if errdefs.IsNotFound(err) { return nil, fmt.Errorf("no running task found: %w", err) } @@ -450,7 +475,7 @@ func loadFifos(response *tasks.GetResponse) *cio.FIFOSet { // we ignore errors here because we don't // want to remove the directory if it isn't // empty - os.Remove(dir) + _ = os.Remove(dir) } return err } diff --git a/vendor/github.com/containerd/containerd/container_checkpoint_opts.go b/vendor/github.com/containerd/containerd/v2/client/container_checkpoint_opts.go similarity index 84% rename from vendor/github.com/containerd/containerd/container_checkpoint_opts.go rename to vendor/github.com/containerd/containerd/v2/client/container_checkpoint_opts.go index 8faf6dee71..4edb937f62 100644 --- a/vendor/github.com/containerd/containerd/container_checkpoint_opts.go +++ b/vendor/github.com/containerd/containerd/v2/client/container_checkpoint_opts.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "bytes" @@ -25,23 +25,19 @@ import ( tasks "github.com/containerd/containerd/api/services/tasks/v1" "github.com/containerd/containerd/api/types/runc/options" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/protobuf" - "github.com/containerd/containerd/protobuf/proto" - "github.com/containerd/containerd/rootfs" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/protobuf/proto" + "github.com/containerd/containerd/v2/pkg/rootfs" "github.com/containerd/platforms" + "github.com/containerd/typeurl/v2" "github.com/opencontainers/go-digest" imagespec "github.com/opencontainers/image-spec/specs-go/v1" ) -var ( - // ErrCheckpointRWUnsupported is returned if the container runtime does not support checkpoint - ErrCheckpointRWUnsupported = errors.New("rw checkpoint is only supported on v2 runtimes") - // ErrMediaTypeNotFound returns an error when a media type in the manifest is unknown - ErrMediaTypeNotFound = errors.New("media type not found") -) +// ErrMediaTypeNotFound returns an error when a media type in the manifest is unknown +var ErrMediaTypeNotFound = errors.New("media type not found") // CheckpointOpts are options to manage the checkpoint operation type CheckpointOpts func(context.Context, *Client, *containers.Container, *imagespec.Index, *options.CheckpointOptions) error @@ -58,13 +54,13 @@ func WithCheckpointImage(ctx context.Context, client *Client, c *containers.Cont // WithCheckpointTask includes the running task func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error { - any, err := protobuf.MarshalAnyToProto(copts) + opt, err := typeurl.MarshalAnyToProto(copts) if err != nil { return nil } task, err := client.TaskService().Checkpoint(ctx, &tasks.CheckpointTaskRequest{ ContainerID: c.ID, - Options: any, + Options: opt, }) if err != nil { return err @@ -80,7 +76,7 @@ func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Conta }) } // save copts - data, err := proto.Marshal(any) + data, err := proto.Marshal(opt) if err != nil { return err } @@ -100,8 +96,8 @@ func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Conta // WithCheckpointRuntime includes the container runtime info func WithCheckpointRuntime(ctx context.Context, client *Client, c *containers.Container, index *imagespec.Index, copts *options.CheckpointOptions) error { if c.Runtime.Options != nil && c.Runtime.Options.GetValue() != nil { - any := protobuf.FromAny(c.Runtime.Options) - data, err := proto.Marshal(any) + opt := typeurl.MarshalProto(c.Runtime.Options) + data, err := proto.Marshal(opt) if err != nil { return err } diff --git a/vendor/github.com/containerd/containerd/container_opts.go b/vendor/github.com/containerd/containerd/v2/client/container_opts.go similarity index 85% rename from vendor/github.com/containerd/containerd/container_opts.go rename to vendor/github.com/containerd/containerd/v2/client/container_opts.go index 4a937032f5..04f2a90621 100644 --- a/vendor/github.com/containerd/containerd/container_opts.go +++ b/vendor/github.com/containerd/containerd/v2/client/container_opts.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -22,14 +22,13 @@ import ( "errors" "fmt" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/protobuf" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/errdefs" "github.com/containerd/typeurl/v2" "github.com/opencontainers/image-spec/identity" v1 "github.com/opencontainers/image-spec/specs-go/v1" @@ -58,18 +57,18 @@ type InfoConfig struct { func WithRuntime(name string, options interface{}) NewContainerOpts { return func(ctx context.Context, client *Client, c *containers.Container) error { var ( - any typeurl.Any - err error + opts typeurl.Any + err error ) if options != nil { - any, err = typeurl.MarshalAny(options) + opts, err = typeurl.MarshalAny(options) if err != nil { return err } } c.Runtime = containers.RuntimeInfo{ Name: name, - Options: any, + Options: opts, } return nil } @@ -120,24 +119,24 @@ func WithImageConfigLabels(image Image) NewContainerOpts { if err != nil { return err } + if !images.IsConfigType(ic.MediaType) { + return fmt.Errorf("unknown image config media type %s", ic.MediaType) + } + var ( ociimage v1.Image config v1.ImageConfig ) - switch ic.MediaType { - case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config: - p, err := content.ReadBlob(ctx, image.ContentStore(), ic) - if err != nil { - return err - } - - if err := json.Unmarshal(p, &ociimage); err != nil { - return err - } - config = ociimage.Config - default: - return fmt.Errorf("unknown image config media type %s", ic.MediaType) + p, err := content.ReadBlob(ctx, image.ContentStore(), ic) + if err != nil { + return err } + + if err = json.Unmarshal(p, &ociimage); err != nil { + return err + } + config = ociimage.Config + c.Labels = config.Labels return nil } @@ -206,38 +205,6 @@ func WithSnapshot(id string) NewContainerOpts { } } -// WithNewSnapshot allocates a new snapshot to be used by the container as the -// root filesystem in read-write mode -func WithNewSnapshot(id string, i Image, opts ...snapshots.Opt) NewContainerOpts { - return func(ctx context.Context, client *Client, c *containers.Container) error { - diffIDs, err := i.RootFS(ctx) - if err != nil { - return err - } - - parent := identity.ChainID(diffIDs).String() - c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter) - if err != nil { - return err - } - s, err := client.getSnapshotter(ctx, c.Snapshotter) - if err != nil { - return err - } - - parent, err = resolveSnapshotOptions(ctx, client, c.Snapshotter, s, parent, opts...) - if err != nil { - return err - } - if _, err := s.Prepare(ctx, id, parent, opts...); err != nil { - return err - } - c.SnapshotKey = id - c.Image = i.Name() - return nil - } -} - // WithSnapshotCleanup deletes the rootfs snapshot allocated for the container func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Container) error { if c.SnapshotKey != "" { @@ -255,11 +222,21 @@ func WithSnapshotCleanup(ctx context.Context, client *Client, c containers.Conta return nil } +// WithNewSnapshot allocates a new snapshot to be used by the container as the +// root filesystem in read-write mode +func WithNewSnapshot(id string, i Image, opts ...snapshots.Opt) NewContainerOpts { + return withNewSnapshot(id, i, false, opts...) +} + // WithNewSnapshotView allocates a new snapshot to be used by the container as the // root filesystem in read-only mode func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainerOpts { + return withNewSnapshot(id, i, true, opts...) +} + +func withNewSnapshot(id string, i Image, readonly bool, opts ...snapshots.Opt) NewContainerOpts { return func(ctx context.Context, client *Client, c *containers.Container) error { - diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform) + diffIDs, err := i.RootFS(ctx) if err != nil { return err } @@ -273,12 +250,17 @@ func WithNewSnapshotView(id string, i Image, opts ...snapshots.Opt) NewContainer if err != nil { return err } - parent, err = resolveSnapshotOptions(ctx, client, c.Snapshotter, s, parent, opts...) if err != nil { return err } - if _, err := s.View(ctx, id, parent, opts...); err != nil { + + if readonly { + _, err = s.View(ctx, id, parent, opts...) + } else { + _, err = s.Prepare(ctx, id, parent, opts...) + } + if err != nil { return err } c.SnapshotKey = id @@ -299,7 +281,7 @@ func WithContainerExtension(name string, extension interface{}) NewContainerOpts return fmt.Errorf("extension key must not be zero-length: %w", errdefs.ErrInvalidArgument) } - any, err := typeurl.MarshalAny(extension) + ext, err := typeurl.MarshalAny(extension) if err != nil { if errors.Is(err, typeurl.ErrNotFound) { return fmt.Errorf("extension %q is not registered with the typeurl package, see `typeurl.Register`: %w", name, err) @@ -310,7 +292,7 @@ func WithContainerExtension(name string, extension interface{}) NewContainerOpts if c.Extensions == nil { c.Extensions = make(map[string]typeurl.Any) } - c.Extensions[name] = any + c.Extensions[name] = ext return nil } } @@ -338,7 +320,7 @@ func WithSpec(s *oci.Spec, opts ...oci.SpecOpts) NewContainerOpts { } var err error - c.Spec, err = protobuf.MarshalAnyToProto(s) + c.Spec, err = typeurl.MarshalAnyToProto(s) return err } } diff --git a/vendor/github.com/containerd/containerd/v2/client/container_opts_unix.go b/vendor/github.com/containerd/containerd/v2/client/container_opts_unix.go new file mode 100644 index 0000000000..fc56292392 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/client/container_opts_unix.go @@ -0,0 +1,147 @@ +//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 client + +import ( + "context" + "fmt" + "os" + "path/filepath" + "syscall" + + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/internal/userns" + + "github.com/containerd/errdefs" + "github.com/opencontainers/image-spec/identity" + "github.com/opencontainers/runtime-spec/specs-go" +) + +// WithRemappedSnapshot creates a new snapshot and remaps the uid/gid for the +// filesystem to be used by a container with user namespaces +func WithRemappedSnapshot(id string, i Image, uid, gid uint32) NewContainerOpts { + uidmaps := []specs.LinuxIDMapping{{ContainerID: 0, HostID: uid, Size: 65536}} + gidmaps := []specs.LinuxIDMapping{{ContainerID: 0, HostID: gid, Size: 65536}} + return withRemappedSnapshotBase(id, i, uidmaps, gidmaps, false) +} + +// WithUserNSRemappedSnapshot creates a new snapshot and remaps the uid/gid for the +// filesystem to be used by a container with user namespaces +func WithUserNSRemappedSnapshot(id string, i Image, uidmaps, gidmaps []specs.LinuxIDMapping) NewContainerOpts { + return withRemappedSnapshotBase(id, i, uidmaps, gidmaps, false) +} + +// WithRemappedSnapshotView is similar to WithRemappedSnapshot but rootfs is mounted as read-only. +func WithRemappedSnapshotView(id string, i Image, uid, gid uint32) NewContainerOpts { + uidmaps := []specs.LinuxIDMapping{{ContainerID: 0, HostID: uid, Size: 65536}} + gidmaps := []specs.LinuxIDMapping{{ContainerID: 0, HostID: gid, Size: 65536}} + return withRemappedSnapshotBase(id, i, uidmaps, gidmaps, true) +} + +// WithUserNSRemappedSnapshotView is similar to WithUserNSRemappedSnapshot but rootfs is mounted as read-only. +func WithUserNSRemappedSnapshotView(id string, i Image, uidmaps, gidmaps []specs.LinuxIDMapping) NewContainerOpts { + return withRemappedSnapshotBase(id, i, uidmaps, gidmaps, true) +} + +func withRemappedSnapshotBase(id string, i Image, uidmaps, gidmaps []specs.LinuxIDMapping, readonly bool) NewContainerOpts { + return func(ctx context.Context, client *Client, c *containers.Container) error { + diffIDs, err := i.(*image).i.RootFS(ctx, client.ContentStore(), client.platform) + if err != nil { + return err + } + + rsn := remappedSnapshot{ + Parent: identity.ChainID(diffIDs).String(), + IDMap: userns.IDMap{UidMap: uidmaps, GidMap: gidmaps}, + } + usernsID, err := rsn.ID() + if err != nil { + return fmt.Errorf("failed to remap snapshot: %w", err) + } + + c.Snapshotter, err = client.resolveSnapshotterName(ctx, c.Snapshotter) + if err != nil { + return err + } + snapshotter, err := client.getSnapshotter(ctx, c.Snapshotter) + if err != nil { + return err + } + if _, err := snapshotter.Stat(ctx, usernsID); err == nil { + if _, err := snapshotter.Prepare(ctx, id, usernsID); err == nil { + c.SnapshotKey = id + c.Image = i.Name() + return nil + } else if !errdefs.IsNotFound(err) { + return err + } + } + mounts, err := snapshotter.Prepare(ctx, usernsID+"-remap", rsn.Parent) + if err != nil { + return err + } + if err := remapRootFS(ctx, mounts, rsn.IDMap); err != nil { + snapshotter.Remove(ctx, usernsID) + return err + } + if err := snapshotter.Commit(ctx, usernsID, usernsID+"-remap"); err != nil { + return err + } + if readonly { + _, err = snapshotter.View(ctx, id, usernsID) + } else { + _, err = snapshotter.Prepare(ctx, id, usernsID) + } + if err != nil { + return err + } + c.SnapshotKey = id + c.Image = i.Name() + return nil + } +} + +func remapRootFS(ctx context.Context, mounts []mount.Mount, idMap userns.IDMap) error { + return mount.WithTempMount(ctx, mounts, func(root string) error { + return filepath.Walk(root, chown(root, idMap)) + }) +} + +func chown(root string, idMap userns.IDMap) filepath.WalkFunc { + return func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + stat := info.Sys().(*syscall.Stat_t) + h, cerr := idMap.ToHost(userns.User{Uid: stat.Uid, Gid: stat.Gid}) + if cerr != nil { + return cerr + } + // be sure the lchown the path as to not de-reference the symlink to a host file + if cerr = os.Lchown(path, int(h.Uid), int(h.Gid)); cerr != nil { + return cerr + } + // we must retain special permissions such as setuid, setgid and sticky bits + if mode := info.Mode(); mode&os.ModeSymlink == 0 && mode&(os.ModeSetuid|os.ModeSetgid|os.ModeSticky) != 0 { + return os.Chmod(path, mode) + } + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/container_restore_opts.go b/vendor/github.com/containerd/containerd/v2/client/container_restore_opts.go similarity index 92% rename from vendor/github.com/containerd/containerd/container_restore_opts.go rename to vendor/github.com/containerd/containerd/v2/client/container_restore_opts.go index 2afc187013..174ae89d12 100644 --- a/vendor/github.com/containerd/containerd/container_restore_opts.go +++ b/vendor/github.com/containerd/containerd/v2/client/container_restore_opts.go @@ -14,18 +14,18 @@ limitations under the License. */ -package containerd +package client import ( "context" "errors" "fmt" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/protobuf/proto" - ptypes "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/protobuf/proto" + ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" "github.com/opencontainers/image-spec/identity" imagespec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -45,7 +45,7 @@ type RestoreOpts func(context.Context, string, *Client, Image, *imagespec.Index) // WithRestoreImage restores the image for the container func WithRestoreImage(ctx context.Context, id string, client *Client, checkpoint Image, index *imagespec.Index) NewContainerOpts { return func(ctx context.Context, client *Client, c *containers.Container) error { - name, ok := index.Annotations[checkpointImageNameLabel] + name, ok := index.Annotations[imagespec.AnnotationRefName] if !ok || name == "" { return ErrImageNameNotFoundInIndex } diff --git a/vendor/github.com/containerd/containerd/containerstore.go b/vendor/github.com/containerd/containerd/v2/client/containerstore.go similarity index 88% rename from vendor/github.com/containerd/containerd/containerstore.go rename to vendor/github.com/containerd/containerd/v2/client/containerstore.go index 331a6f41de..a908737c98 100644 --- a/vendor/github.com/containerd/containerd/containerstore.go +++ b/vendor/github.com/containerd/containerd/v2/client/containerstore.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -22,13 +22,14 @@ import ( "io" containersapi "github.com/containerd/containerd/api/services/containers/v1" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/protobuf" - ptypes "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/errdefs/pkg/errgrpc" "github.com/containerd/typeurl/v2" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" + + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/protobuf" + ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" ) type remoteContainers struct { @@ -49,7 +50,7 @@ func (r *remoteContainers) Get(ctx context.Context, id string) (containers.Conta ID: id, }) if err != nil { - return containers.Container{}, errdefs.FromGRPC(err) + return containers.Container{}, errgrpc.ToNative(err) } return containerFromProto(resp.Container), nil @@ -71,7 +72,7 @@ func (r *remoteContainers) list(ctx context.Context, filters ...string) ([]conta Filters: filters, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } return containersFromProto(resp.Containers), nil } @@ -83,7 +84,7 @@ func (r *remoteContainers) stream(ctx context.Context, filters ...string) ([]con Filters: filters, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } var containers []containers.Container for { @@ -97,7 +98,7 @@ func (r *remoteContainers) stream(ctx context.Context, filters ...string) ([]con return nil, errStreamNotAvailable } } - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } select { case <-ctx.Done(): @@ -113,7 +114,7 @@ func (r *remoteContainers) Create(ctx context.Context, container containers.Cont Container: containerToProto(&container), }) if err != nil { - return containers.Container{}, errdefs.FromGRPC(err) + return containers.Container{}, errgrpc.ToNative(err) } return containerFromProto(created.Container), nil @@ -133,7 +134,7 @@ func (r *remoteContainers) Update(ctx context.Context, container containers.Cont UpdateMask: updateMask, }) if err != nil { - return containers.Container{}, errdefs.FromGRPC(err) + return containers.Container{}, errgrpc.ToNative(err) } return containerFromProto(updated.Container), nil @@ -145,14 +146,14 @@ func (r *remoteContainers) Delete(ctx context.Context, id string) error { ID: id, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func containerToProto(container *containers.Container) *containersapi.Container { extensions := make(map[string]*ptypes.Any) for k, v := range container.Extensions { - extensions[k] = protobuf.FromAny(v) + extensions[k] = typeurl.MarshalProto(v) } return &containersapi.Container{ ID: container.ID, @@ -160,9 +161,9 @@ func containerToProto(container *containers.Container) *containersapi.Container Image: container.Image, Runtime: &containersapi.Container_Runtime{ Name: container.Runtime.Name, - Options: protobuf.FromAny(container.Runtime.Options), + Options: typeurl.MarshalProto(container.Runtime.Options), }, - Spec: protobuf.FromAny(container.Spec), + Spec: typeurl.MarshalProto(container.Spec), Snapshotter: container.Snapshotter, SnapshotKey: container.SnapshotKey, Extensions: extensions, diff --git a/vendor/github.com/containerd/containerd/diff.go b/vendor/github.com/containerd/containerd/v2/client/diff.go similarity index 89% rename from vendor/github.com/containerd/containerd/diff.go rename to vendor/github.com/containerd/containerd/v2/client/diff.go index 0b1d44ed5b..2af19d4a7a 100644 --- a/vendor/github.com/containerd/containerd/diff.go +++ b/vendor/github.com/containerd/containerd/v2/client/diff.go @@ -14,12 +14,12 @@ limitations under the License. */ -package containerd +package client import ( diffapi "github.com/containerd/containerd/api/services/diff/v1" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/diff/proxy" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/diff/proxy" ) // DiffService handles the computation and application of diffs diff --git a/vendor/github.com/containerd/containerd/events.go b/vendor/github.com/containerd/containerd/v2/client/events.go similarity index 88% rename from vendor/github.com/containerd/containerd/events.go rename to vendor/github.com/containerd/containerd/v2/client/events.go index c95a64f7ca..3f6e252b37 100644 --- a/vendor/github.com/containerd/containerd/events.go +++ b/vendor/github.com/containerd/containerd/v2/client/events.go @@ -14,18 +14,18 @@ limitations under the License. */ -package containerd +package client import ( "context" - "github.com/containerd/typeurl/v2" - eventsapi "github.com/containerd/containerd/api/services/events/v1" "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/events" - "github.com/containerd/containerd/protobuf" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/typeurl/v2" + + "github.com/containerd/containerd/v2/core/events" + "github.com/containerd/containerd/v2/pkg/protobuf" ) // EventService handles the publish, forward and subscribe of events. @@ -48,16 +48,16 @@ type eventRemote struct { } func (e *eventRemote) Publish(ctx context.Context, topic string, event events.Event) error { - any, err := typeurl.MarshalAny(event) + evt, err := typeurl.MarshalAny(event) if err != nil { return err } req := &eventsapi.PublishRequest{ Topic: topic, - Event: protobuf.FromAny(any), + Event: typeurl.MarshalProto(evt), } if _, err := e.client.Publish(ctx, req); err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } @@ -68,11 +68,11 @@ func (e *eventRemote) Forward(ctx context.Context, envelope *events.Envelope) er Timestamp: protobuf.ToTimestamp(envelope.Timestamp), Namespace: envelope.Namespace, Topic: envelope.Topic, - Event: protobuf.FromAny(envelope.Event), + Event: typeurl.MarshalProto(envelope.Event), }, } if _, err := e.client.Forward(ctx, req); err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } diff --git a/vendor/github.com/containerd/containerd/export.go b/vendor/github.com/containerd/containerd/v2/client/export.go similarity index 92% rename from vendor/github.com/containerd/containerd/export.go rename to vendor/github.com/containerd/containerd/v2/client/export.go index 81f199226d..bd34c65d42 100644 --- a/vendor/github.com/containerd/containerd/export.go +++ b/vendor/github.com/containerd/containerd/v2/client/export.go @@ -14,13 +14,13 @@ limitations under the License. */ -package containerd +package client import ( "context" "io" - "github.com/containerd/containerd/images/archive" + "github.com/containerd/containerd/v2/core/images/archive" ) // Export exports images to a Tar stream. diff --git a/vendor/github.com/containerd/containerd/grpc.go b/vendor/github.com/containerd/containerd/v2/client/grpc.go similarity index 95% rename from vendor/github.com/containerd/containerd/grpc.go rename to vendor/github.com/containerd/containerd/v2/client/grpc.go index c3506d7357..99325094a9 100644 --- a/vendor/github.com/containerd/containerd/grpc.go +++ b/vendor/github.com/containerd/containerd/v2/client/grpc.go @@ -14,12 +14,12 @@ limitations under the License. */ -package containerd +package client import ( "context" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/pkg/namespaces" "google.golang.org/grpc" ) diff --git a/vendor/github.com/containerd/containerd/image.go b/vendor/github.com/containerd/containerd/v2/client/image.go similarity index 75% rename from vendor/github.com/containerd/containerd/image.go rename to vendor/github.com/containerd/containerd/v2/client/image.go index 2497a3c144..355bcba73e 100644 --- a/vendor/github.com/containerd/containerd/image.go +++ b/vendor/github.com/containerd/containerd/v2/client/image.go @@ -14,30 +14,28 @@ limitations under the License. */ -package containerd +package client import ( "context" "encoding/json" "errors" "fmt" - "strings" - "sync/atomic" + "sync" + "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/images/usage" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/internal/kmutex" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/rootfs" + "github.com/containerd/errdefs" "github.com/containerd/platforms" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "golang.org/x/sync/semaphore" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/pkg/kmutex" - "github.com/containerd/containerd/rootfs" - "github.com/containerd/containerd/snapshots" ) // Image describes an image used by containers @@ -58,7 +56,7 @@ type Image interface { Usage(context.Context, ...UsageOpt) (int64, error) // Config descriptor for the image. Config(ctx context.Context) (ocispec.Descriptor, error) - // IsUnpacked returns whether or not an image is unpacked. + // IsUnpacked returns whether an image is unpacked. IsUnpacked(context.Context, string) (bool, error) // ContentStore provides a content store which contains image blob data ContentStore() content.Store @@ -138,6 +136,9 @@ type image struct { i images.Image platform platforms.MatchComparer + diffIDs []digest.Digest + + mu sync.Mutex } func (i *image) Metadata() images.Image { @@ -157,12 +158,23 @@ func (i *image) Labels() map[string]string { } func (i *image) RootFS(ctx context.Context) ([]digest.Digest, error) { + i.mu.Lock() + defer i.mu.Unlock() + if i.diffIDs != nil { + return i.diffIDs, nil + } + provider := i.client.ContentStore() - return i.i.RootFS(ctx, provider, i.platform) + diffIDs, err := i.i.RootFS(ctx, provider, i.platform) + if err != nil { + return nil, err + } + i.diffIDs = diffIDs + return diffIDs, nil } func (i *image) Size(ctx context.Context) (int64, error) { - return i.Usage(ctx, WithUsageManifestLimit(1), WithManifestUsage()) + return usage.CalculateImageUsage(ctx, i.i, i.client.ContentStore(), usage.WithManifestLimit(i.platform, 1), usage.WithManifestUsage()) } func (i *image) Usage(ctx context.Context, opts ...UsageOpt) (int64, error) { @@ -173,86 +185,18 @@ func (i *image) Usage(ctx context.Context, opts ...UsageOpt) (int64, error) { } } - var ( - provider = i.client.ContentStore() - handler = images.ChildrenHandler(provider) - size int64 - mustExist bool - ) - + var usageOpts []usage.Opt if config.manifestLimit != nil { - handler = images.LimitManifests(handler, i.platform, *config.manifestLimit) - mustExist = true + usageOpts = append(usageOpts, usage.WithManifestLimit(i.platform, *config.manifestLimit)) + } + if config.snapshots { + usageOpts = append(usageOpts, usage.WithSnapshotters(i.client.SnapshotService)) + } + if config.manifestOnly { + usageOpts = append(usageOpts, usage.WithManifestUsage()) } - var wh images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { - var usage int64 - children, err := handler(ctx, desc) - if err != nil { - if !errdefs.IsNotFound(err) || mustExist { - return nil, err - } - if !config.manifestOnly { - // Do not count size of non-existent objects - desc.Size = 0 - } - } else if config.snapshots || !config.manifestOnly { - info, err := provider.Info(ctx, desc.Digest) - if err != nil { - if !errdefs.IsNotFound(err) { - return nil, err - } - if !config.manifestOnly { - // Do not count size of non-existent objects - desc.Size = 0 - } - } else if info.Size > desc.Size { - // Count actual usage, Size may be unset or -1 - desc.Size = info.Size - } - - if config.snapshots { - for k, v := range info.Labels { - const prefix = "containerd.io/gc.ref.snapshot." - if !strings.HasPrefix(k, prefix) { - continue - } - - sn := i.client.SnapshotService(k[len(prefix):]) - if sn == nil { - continue - } - - u, err := sn.Usage(ctx, v) - if err != nil { - if !errdefs.IsNotFound(err) && !errdefs.IsInvalidArgument(err) { - return nil, err - } - } else { - usage += u.Size - } - } - } - } - - // Ignore unknown sizes. Generally unknown sizes should - // never be set in manifests, however, the usage - // calculation does not need to enforce this. - if desc.Size >= 0 { - usage += desc.Size - } - - atomic.AddInt64(&size, usage) - - return children, nil - } - - l := semaphore.NewWeighted(3) - if err := images.Dispatch(ctx, wh, l, i.i.Target); err != nil { - return 0, err - } - - return size, nil + return usage.CalculateImageUsage(ctx, i.i, i.client.ContentStore(), usageOpts...) } func (i *image) Config(ctx context.Context) (ocispec.Descriptor, error) { @@ -265,22 +209,20 @@ func (i *image) IsUnpacked(ctx context.Context, snapshotterName string) (bool, e if err != nil { return false, err } - cs := i.client.ContentStore() - diffs, err := i.i.RootFS(ctx, cs, i.platform) + diffs, err := i.RootFS(ctx) if err != nil { return false, err } - chainID := identity.ChainID(diffs) - _, err = sn.Stat(ctx, chainID.String()) - if err == nil { - return true, nil - } else if !errdefs.IsNotFound(err) { + if _, err := sn.Stat(ctx, identity.ChainID(diffs).String()); err != nil { + if errdefs.IsNotFound(err) { + return false, nil + } return false, err } - return false, nil + return true, nil } func (i *image) Spec(ctx context.Context) (ocispec.Image, error) { @@ -364,7 +306,7 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...Unpa return err } - layers, err := i.getLayers(ctx, i.platform, manifest) + layers, err := i.getLayers(ctx, manifest) if err != nil { return err } @@ -393,7 +335,7 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...Unpa for _, layer := range layers { unpacked, err = rootfs.ApplyLayerWithOpts(ctx, layer, chain, sn, a, config.SnapshotOpts, config.ApplyOpts) if err != nil { - return err + return fmt.Errorf("apply layer error for %q: %w", i.Name(), err) } if unpacked { @@ -418,12 +360,12 @@ func (i *image) Unpack(ctx context.Context, snapshotterName string, opts ...Unpa return err } - rootfs := identity.ChainID(chain).String() + rootFS := identity.ChainID(chain).String() cinfo := content.Info{ Digest: desc.Digest, Labels: map[string]string{ - fmt.Sprintf("containerd.io/gc.ref.snapshot.%s", snapshotterName): rootfs, + fmt.Sprintf("containerd.io/gc.ref.snapshot.%s", snapshotterName): rootFS, }, } @@ -440,9 +382,8 @@ func (i *image) getManifest(ctx context.Context, platform platforms.MatchCompare return manifest, nil } -func (i *image) getLayers(ctx context.Context, platform platforms.MatchComparer, manifest ocispec.Manifest) ([]rootfs.Layer, error) { - cs := i.ContentStore() - diffIDs, err := i.i.RootFS(ctx, cs, platform) +func (i *image) getLayers(ctx context.Context, manifest ocispec.Manifest) ([]rootfs.Layer, error) { + diffIDs, err := i.RootFS(ctx) if err != nil { return nil, fmt.Errorf("failed to resolve rootfs: %w", err) } @@ -469,27 +410,13 @@ func (i *image) getLayers(ctx context.Context, platform platforms.MatchComparer, return layers, nil } -func (i *image) getManifestPlatform(ctx context.Context, manifest ocispec.Manifest) (ocispec.Platform, error) { - cs := i.ContentStore() - p, err := content.ReadBlob(ctx, cs, manifest.Config) - if err != nil { - return ocispec.Platform{}, err - } - - var image ocispec.Image - if err := json.Unmarshal(p, &image); err != nil { - return ocispec.Platform{}, err - } - return platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture}), nil -} - func (i *image) checkSnapshotterSupport(ctx context.Context, snapshotterName string, manifest ocispec.Manifest) error { snapshotterPlatformMatcher, err := i.client.GetSnapshotterSupportedPlatforms(ctx, snapshotterName) if err != nil { return err } - manifestPlatform, err := i.getManifestPlatform(ctx, manifest) + manifestPlatform, err := images.ConfigPlatform(ctx, i.ContentStore(), manifest.Config) if err != nil { return err } diff --git a/vendor/github.com/containerd/containerd/image_store.go b/vendor/github.com/containerd/containerd/v2/client/image_store.go similarity index 73% rename from vendor/github.com/containerd/containerd/image_store.go rename to vendor/github.com/containerd/containerd/v2/client/image_store.go index 524a7a6727..c52e99ea1a 100644 --- a/vendor/github.com/containerd/containerd/image_store.go +++ b/vendor/github.com/containerd/containerd/v2/client/image_store.go @@ -14,21 +14,20 @@ limitations under the License. */ -package containerd +package client import ( "context" imagesapi "github.com/containerd/containerd/api/services/images/v1" - "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/pkg/epoch" - "github.com/containerd/containerd/protobuf" - ptypes "github.com/containerd/containerd/protobuf/types" - "github.com/opencontainers/go-digest" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/errdefs/pkg/errgrpc" "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/epoch" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/protobuf" + ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" ) type remoteImages struct { @@ -47,7 +46,7 @@ func (s *remoteImages) Get(ctx context.Context, name string) (images.Image, erro Name: name, }) if err != nil { - return images.Image{}, errdefs.FromGRPC(err) + return images.Image{}, errgrpc.ToNative(err) } return imageFromProto(resp.Image), nil @@ -58,7 +57,7 @@ func (s *remoteImages) List(ctx context.Context, filters ...string) ([]images.Im Filters: filters, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } return imagesFromProto(resp.Images), nil @@ -73,7 +72,7 @@ func (s *remoteImages) Create(ctx context.Context, image images.Image) (images.I } created, err := s.client.Create(ctx, req) if err != nil { - return images.Image{}, errdefs.FromGRPC(err) + return images.Image{}, errgrpc.ToNative(err) } return imageFromProto(created.Image), nil @@ -95,7 +94,7 @@ func (s *remoteImages) Update(ctx context.Context, image images.Image, fieldpath } updated, err := s.client.Update(ctx, req) if err != nil { - return images.Image{}, errdefs.FromGRPC(err) + return images.Image{}, errgrpc.ToNative(err) } return imageFromProto(updated.Image), nil @@ -108,19 +107,22 @@ func (s *remoteImages) Delete(ctx context.Context, name string, opts ...images.D return err } } - _, err := s.client.Delete(ctx, &imagesapi.DeleteImageRequest{ + req := &imagesapi.DeleteImageRequest{ Name: name, Sync: do.Synchronous, - }) - - return errdefs.FromGRPC(err) + } + if do.Target != nil { + req.Target = oci.DescriptorToProto(*do.Target) + } + _, err := s.client.Delete(ctx, req) + return errgrpc.ToNative(err) } func imageToProto(image *images.Image) *imagesapi.Image { return &imagesapi.Image{ Name: image.Name, Labels: image.Labels, - Target: descToProto(&image.Target), + Target: oci.DescriptorToProto(image.Target), CreatedAt: protobuf.ToTimestamp(image.CreatedAt), UpdatedAt: protobuf.ToTimestamp(image.UpdatedAt), } @@ -130,7 +132,7 @@ func imageFromProto(imagepb *imagesapi.Image) images.Image { return images.Image{ Name: imagepb.Name, Labels: imagepb.Labels, - Target: descFromProto(imagepb.Target), + Target: oci.DescriptorFromProto(imagepb.Target), CreatedAt: protobuf.FromTimestamp(imagepb.CreatedAt), UpdatedAt: protobuf.FromTimestamp(imagepb.UpdatedAt), } @@ -146,21 +148,3 @@ func imagesFromProto(imagespb []*imagesapi.Image) []images.Image { return images } - -func descFromProto(desc *types.Descriptor) ocispec.Descriptor { - return ocispec.Descriptor{ - MediaType: desc.MediaType, - Size: desc.Size, - Digest: digest.Digest(desc.Digest), - Annotations: desc.Annotations, - } -} - -func descToProto(desc *ocispec.Descriptor) *types.Descriptor { - return &types.Descriptor{ - MediaType: desc.MediaType, - Size: desc.Size, - Digest: desc.Digest.String(), - Annotations: desc.Annotations, - } -} diff --git a/vendor/github.com/containerd/containerd/import.go b/vendor/github.com/containerd/containerd/v2/client/import.go similarity index 90% rename from vendor/github.com/containerd/containerd/import.go rename to vendor/github.com/containerd/containerd/v2/client/import.go index 79c87fdd4c..65ae95e22d 100644 --- a/vendor/github.com/containerd/containerd/import.go +++ b/vendor/github.com/containerd/containerd/v2/client/import.go @@ -14,21 +14,18 @@ limitations under the License. */ -package containerd +package client import ( "context" - "encoding/json" "io" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/images/archive" + "github.com/containerd/errdefs" "github.com/containerd/platforms" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/archive" ) type importOpts struct { @@ -41,6 +38,7 @@ type importOpts struct { compress bool discardLayers bool skipMissing bool + imageLabels map[string]string } // ImportOpt allows the caller to specify import specific options @@ -55,6 +53,14 @@ func WithImageRefTranslator(f func(string) string) ImportOpt { } } +// WithImageLabels are the image labels to apply to a new image +func WithImageLabels(labels map[string]string) ImportOpt { + return func(c *importOpts) error { + c.imageLabels = labels + return nil + } +} + // WithDigestRef is used to create digest images for each // manifest in the index. func WithDigestRef(f func(digest.Digest) string) ImportOpt { @@ -183,16 +189,11 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt return children, err } - p, err := content.ReadBlob(ctx, cs, desc) + idx, err := decodeIndex(ctx, cs, desc) if err != nil { return nil, err } - var idx ocispec.Index - if err := json.Unmarshal(p, &idx); err != nil { - return nil, err - } - for _, m := range idx.Manifests { name := imageName(m.Annotations, iopts.imageRefT) if name != "" { @@ -231,7 +232,12 @@ func (c *Client) Import(ctx context.Context, reader io.Reader, opts ...ImportOpt } for i := range imgs { - img, err := is.Update(ctx, imgs[i], "target") + fieldsPath := []string{"target"} + if iopts.imageLabels != nil { + fieldsPath = append(fieldsPath, "labels") + imgs[i].Labels = iopts.imageLabels + } + img, err := is.Update(ctx, imgs[i], fieldsPath...) if err != nil { if !errdefs.IsNotFound(err) { return nil, err diff --git a/vendor/github.com/containerd/containerd/install.go b/vendor/github.com/containerd/containerd/v2/client/install.go similarity index 90% rename from vendor/github.com/containerd/containerd/install.go rename to vendor/github.com/containerd/containerd/v2/client/install.go index a307960b8c..2f636b277c 100644 --- a/vendor/github.com/containerd/containerd/install.go +++ b/vendor/github.com/containerd/containerd/v2/client/install.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "archive/tar" @@ -26,10 +26,10 @@ import ( "runtime" "strings" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/archive/compression" - "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/containerd/v2/pkg/archive" + "github.com/containerd/containerd/v2/pkg/archive/compression" ) // Install a binary image into the opt service. @@ -112,8 +112,7 @@ func (c *Client) getInstallPath(ctx context.Context, config InstallConfig) (stri if config.Path != "" { return config.Path, nil } - filters := []string{"id==opt"} - resp, err := c.IntrospectionService().Plugins(ctx, filters) + resp, err := c.IntrospectionService().Plugins(ctx, "id==opt") if err != nil { return "", err } diff --git a/vendor/github.com/containerd/containerd/install_opts.go b/vendor/github.com/containerd/containerd/v2/client/install_opts.go similarity index 98% rename from vendor/github.com/containerd/containerd/install_opts.go rename to vendor/github.com/containerd/containerd/v2/client/install_opts.go index b0c9213cb2..c42d910e87 100644 --- a/vendor/github.com/containerd/containerd/install_opts.go +++ b/vendor/github.com/containerd/containerd/v2/client/install_opts.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client // InstallOpts configures binary installs type InstallOpts func(*InstallConfig) diff --git a/vendor/github.com/containerd/containerd/lease.go b/vendor/github.com/containerd/containerd/v2/client/lease.go similarity index 95% rename from vendor/github.com/containerd/containerd/lease.go rename to vendor/github.com/containerd/containerd/v2/client/lease.go index 07ea6d9324..e0608a7c6c 100644 --- a/vendor/github.com/containerd/containerd/lease.go +++ b/vendor/github.com/containerd/containerd/v2/client/lease.go @@ -14,13 +14,13 @@ limitations under the License. */ -package containerd +package client import ( "context" "time" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/leases" ) // WithLease attaches a lease on the context diff --git a/vendor/github.com/containerd/containerd/namespaces.go b/vendor/github.com/containerd/containerd/v2/client/namespaces.go similarity index 88% rename from vendor/github.com/containerd/containerd/namespaces.go rename to vendor/github.com/containerd/containerd/v2/client/namespaces.go index 83ee828dd0..ca93e80f62 100644 --- a/vendor/github.com/containerd/containerd/namespaces.go +++ b/vendor/github.com/containerd/containerd/v2/client/namespaces.go @@ -14,16 +14,17 @@ limitations under the License. */ -package containerd +package client import ( "context" "strings" api "github.com/containerd/containerd/api/services/namespaces/v1" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/errdefs/pkg/errgrpc" + + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/pkg/protobuf/types" ) // NewNamespaceStoreFromClient returns a new namespace store @@ -45,7 +46,7 @@ func (r *remoteNamespaces) Create(ctx context.Context, namespace string, labels _, err := r.client.Create(ctx, &req) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil @@ -57,7 +58,7 @@ func (r *remoteNamespaces) Labels(ctx context.Context, namespace string) (map[st resp, err := r.client.Get(ctx, &req) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } return resp.Namespace.Labels, nil @@ -77,7 +78,7 @@ func (r *remoteNamespaces) SetLabel(ctx context.Context, namespace, key, value s _, err := r.client.Update(ctx, &req) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil @@ -88,7 +89,7 @@ func (r *remoteNamespaces) List(ctx context.Context) ([]string, error) { resp, err := r.client.List(ctx, &req) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } var namespaces []string @@ -114,7 +115,7 @@ func (r *remoteNamespaces) Delete(ctx context.Context, namespace string, opts .. } _, err := r.client.Delete(ctx, &req) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil diff --git a/vendor/github.com/containerd/containerd/oss_fuzz.go b/vendor/github.com/containerd/containerd/v2/client/oss_fuzz.go similarity index 97% rename from vendor/github.com/containerd/containerd/oss_fuzz.go rename to vendor/github.com/containerd/containerd/v2/client/oss_fuzz.go index 8d1def4f09..429592667d 100644 --- a/vendor/github.com/containerd/containerd/oss_fuzz.go +++ b/vendor/github.com/containerd/containerd/v2/client/oss_fuzz.go @@ -16,7 +16,7 @@ limitations under the License. */ -package containerd +package client import ( "github.com/AdamKorcz/go-118-fuzz-build/testing" diff --git a/vendor/github.com/containerd/containerd/process.go b/vendor/github.com/containerd/containerd/v2/client/process.go similarity index 77% rename from vendor/github.com/containerd/containerd/process.go rename to vendor/github.com/containerd/containerd/v2/client/process.go index 73d8f86625..e451eaa7d1 100644 --- a/vendor/github.com/containerd/containerd/process.go +++ b/vendor/github.com/containerd/containerd/v2/client/process.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -24,9 +24,12 @@ import ( "time" "github.com/containerd/containerd/api/services/tasks/v1" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/protobuf" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" + + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/protobuf" + "github.com/containerd/containerd/v2/pkg/tracing" ) // Process represents a system process @@ -82,13 +85,13 @@ func (s ExitStatus) Result() (uint32, time.Time, error) { } // ExitCode returns the exit code of the process. -// This is only valid is Error() returns nil +// This is only valid if Error() returns nil. func (s ExitStatus) ExitCode() uint32 { return s.code } // ExitTime returns the exit time of the process -// This is only valid is Error() returns nil +// This is only valid if Error() returns nil. func (s ExitStatus) ExitTime() time.Time { return s.exitedAt } @@ -118,6 +121,11 @@ func (p *process) Pid() uint32 { // Start starts the exec process func (p *process) Start(ctx context.Context) error { + ctx, span := tracing.StartSpan(ctx, "process.Start", + tracing.WithAttribute("process.id", p.ID()), + tracing.WithAttribute("process.task.id", p.task.ID()), + ) + defer span.End() r, err := p.task.client.TaskService().Start(ctx, &tasks.StartRequest{ ContainerID: p.task.id, ExecID: p.id, @@ -128,13 +136,20 @@ func (p *process) Start(ctx context.Context) error { p.io.Wait() p.io.Close() } - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } + span.SetAttributes(tracing.Attribute("process.pid", int(r.Pid))) p.pid = r.Pid return nil } func (p *process) Kill(ctx context.Context, s syscall.Signal, opts ...KillOpts) error { + ctx, span := tracing.StartSpan(ctx, "process.Kill", + tracing.WithAttribute("process.id", p.ID()), + tracing.WithAttribute("process.pid", int(p.Pid())), + tracing.WithAttribute("process.task.id", p.task.ID()), + ) + defer span.End() var i KillInfo for _, o := range opts { if err := o(ctx, &i); err != nil { @@ -147,13 +162,18 @@ func (p *process) Kill(ctx context.Context, s syscall.Signal, opts ...KillOpts) ExecID: p.id, All: i.All, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (p *process) Wait(ctx context.Context) (<-chan ExitStatus, error) { c := make(chan ExitStatus, 1) go func() { defer close(c) + ctx, span := tracing.StartSpan(ctx, "process.Wait", + tracing.WithAttribute("process.id", p.ID()), + tracing.WithAttribute("process.task.id", p.task.ID()), + ) + defer span.End() r, err := p.task.client.TaskService().Wait(ctx, &tasks.WaitRequest{ ContainerID: p.task.id, ExecID: p.id, @@ -174,6 +194,10 @@ func (p *process) Wait(ctx context.Context) (<-chan ExitStatus, error) { } func (p *process) CloseIO(ctx context.Context, opts ...IOCloserOpts) error { + ctx, span := tracing.StartSpan(ctx, "process.CloseIO", + tracing.WithAttribute("process.id", p.ID()), + ) + defer span.End() r := &tasks.CloseIORequest{ ContainerID: p.task.id, ExecID: p.id, @@ -184,7 +208,7 @@ func (p *process) CloseIO(ctx context.Context, opts ...IOCloserOpts) error { } r.Stdin = i.Stdin _, err := p.task.client.TaskService().CloseIO(ctx, r) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (p *process) IO() cio.IO { @@ -192,16 +216,24 @@ func (p *process) IO() cio.IO { } func (p *process) Resize(ctx context.Context, w, h uint32) error { + ctx, span := tracing.StartSpan(ctx, "process.Resize", + tracing.WithAttribute("process.id", p.ID()), + ) + defer span.End() _, err := p.task.client.TaskService().ResizePty(ctx, &tasks.ResizePtyRequest{ ContainerID: p.task.id, Width: w, Height: h, ExecID: p.id, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (p *process) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStatus, error) { + ctx, span := tracing.StartSpan(ctx, "process.Delete", + tracing.WithAttribute("process.id", p.ID()), + ) + defer span.End() for _, o := range opts { if err := o(ctx, p); err != nil { return nil, err @@ -220,7 +252,7 @@ func (p *process) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitS ExecID: p.id, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } if p.io != nil { p.io.Cancel() @@ -236,10 +268,13 @@ func (p *process) Status(ctx context.Context) (Status, error) { ExecID: p.id, }) if err != nil { - return Status{}, errdefs.FromGRPC(err) + return Status{}, errgrpc.ToNative(err) } + status := ProcessStatus(strings.ToLower(r.Process.Status.String())) + exitStatus := r.Process.ExitStatus + return Status{ - Status: ProcessStatus(strings.ToLower(r.Process.Status.String())), - ExitStatus: r.Process.ExitStatus, + Status: status, + ExitStatus: exitStatus, }, nil } diff --git a/vendor/github.com/containerd/containerd/pull.go b/vendor/github.com/containerd/containerd/v2/client/pull.go similarity index 93% rename from vendor/github.com/containerd/containerd/pull.go rename to vendor/github.com/containerd/containerd/v2/client/pull.go index c5d3e969a9..060c729dfe 100644 --- a/vendor/github.com/containerd/containerd/pull.go +++ b/vendor/github.com/containerd/containerd/v2/client/pull.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -24,15 +24,14 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/semaphore" + "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/core/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. + "github.com/containerd/containerd/v2/core/unpack" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/errdefs" "github.com/containerd/platforms" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/pkg/unpack" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - "github.com/containerd/containerd/tracing" ) const ( @@ -198,7 +197,10 @@ func (c *Client) fetch(ctx context.Context, rCtx *RemoteContext, ref string, lim ) if desc.MediaType == images.MediaTypeDockerSchema1Manifest && rCtx.ConvertSchema1 { - schema1Converter := schema1.NewConverter(store, fetcher) + schema1Converter, err := schema1.NewConverter(store, fetcher) + if err != nil { + return images.Image{}, fmt.Errorf("failed to get converter for %q: %w", ref, err) + } handler = images.Handlers(append(rCtx.BaseHandlers, schema1Converter)...) diff --git a/vendor/github.com/containerd/containerd/sandbox.go b/vendor/github.com/containerd/containerd/v2/client/sandbox.go similarity index 83% rename from vendor/github.com/containerd/containerd/sandbox.go rename to vendor/github.com/containerd/containerd/v2/client/sandbox.go index 2e46da9f32..335debe226 100644 --- a/vendor/github.com/containerd/containerd/sandbox.go +++ b/vendor/github.com/containerd/containerd/v2/client/sandbox.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -22,19 +22,21 @@ import ( "fmt" "time" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/protobuf/types" - api "github.com/containerd/containerd/sandbox" + "github.com/containerd/errdefs" "github.com/containerd/typeurl/v2" + + "github.com/containerd/containerd/v2/core/containers" + api "github.com/containerd/containerd/v2/core/sandbox" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/protobuf/types" ) // Sandbox is a high level client to containerd's sandboxes. type Sandbox interface { // ID is a sandbox identifier ID() string - // PID returns sandbox's process PID or error if its not yet started. - PID() (uint32, error) + // Metadata returns metadata of the sandbox + Metadata() api.Sandbox // NewContainer creates new container that will belong to this sandbox NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) // Labels returns the labels set on the sandbox @@ -50,7 +52,6 @@ type Sandbox interface { } type sandboxClient struct { - pid *uint32 client *Client metadata api.Sandbox } @@ -59,12 +60,8 @@ func (s *sandboxClient) ID() string { return s.metadata.ID } -func (s *sandboxClient) PID() (uint32, error) { - if s.pid == nil { - return 0, fmt.Errorf("sandbox not started") - } - - return *s.pid, nil +func (s *sandboxClient) Metadata() api.Sandbox { + return s.metadata } func (s *sandboxClient) NewContainer(ctx context.Context, id string, opts ...NewContainerOpts) (Container, error) { @@ -81,12 +78,11 @@ func (s *sandboxClient) Labels(ctx context.Context) (map[string]string, error) { } func (s *sandboxClient) Start(ctx context.Context) error { - resp, err := s.client.SandboxController().Start(ctx, s.ID()) + _, err := s.client.SandboxController(s.metadata.Sandboxer).Start(ctx, s.ID()) if err != nil { return err } - s.pid = &resp.Pid return nil } @@ -95,7 +91,7 @@ func (s *sandboxClient) Wait(ctx context.Context) (<-chan ExitStatus, error) { go func() { defer close(c) - exitStatus, err := s.client.SandboxController().Wait(ctx, s.ID()) + exitStatus, err := s.client.SandboxController(s.metadata.Sandboxer).Wait(ctx, s.ID()) if err != nil { c <- ExitStatus{ code: UnknownExitStatus, @@ -114,15 +110,15 @@ func (s *sandboxClient) Wait(ctx context.Context) (<-chan ExitStatus, error) { } func (s *sandboxClient) Stop(ctx context.Context) error { - return s.client.SandboxController().Stop(ctx, s.ID()) + return s.client.SandboxController(s.metadata.Sandboxer).Stop(ctx, s.ID()) } func (s *sandboxClient) Shutdown(ctx context.Context) error { - if err := s.client.SandboxController().Shutdown(ctx, s.ID()); err != nil { + if err := s.client.SandboxController(s.metadata.Sandboxer).Shutdown(ctx, s.ID()); err != nil && errdefs.IsNotFound(err) { return fmt.Errorf("failed to shutdown sandbox: %w", err) } - if err := s.client.SandboxStore().Delete(ctx, s.ID()); err != nil { + if err := s.client.SandboxStore().Delete(ctx, s.ID()); err != nil && !errdefs.IsNotFound(err) { return fmt.Errorf("failed to delete sandbox from store: %w", err) } @@ -153,7 +149,6 @@ func (c *Client) NewSandbox(ctx context.Context, sandboxID string, opts ...NewSa } return &sandboxClient{ - pid: nil, // Not yet started client: c, metadata: metadata, }, nil @@ -166,13 +161,7 @@ func (c *Client) LoadSandbox(ctx context.Context, id string) (Sandbox, error) { return nil, err } - status, err := c.SandboxController().Status(ctx, id, false) - if err != nil { - return nil, fmt.Errorf("failed to load sandbox %s, status request failed: %w", id, err) - } - return &sandboxClient{ - pid: &status.Pid, client: c, metadata: sandbox, }, nil @@ -222,19 +211,19 @@ func WithSandboxSpec(s *oci.Spec, opts ...oci.SpecOpts) NewSandboxOpts { } // WithSandboxExtension attaches an extension to sandbox -func WithSandboxExtension(name string, ext interface{}) NewSandboxOpts { +func WithSandboxExtension(name string, extension interface{}) NewSandboxOpts { return func(ctx context.Context, client *Client, s *api.Sandbox) error { if s.Extensions == nil { s.Extensions = make(map[string]typeurl.Any) } - any, err := typeurl.MarshalAny(ext) + ext, err := typeurl.MarshalAny(extension) if err != nil { return fmt.Errorf("failed to marshal sandbox extension: %w", err) } - s.Extensions[name] = any - return err + s.Extensions[name] = ext + return nil } } diff --git a/vendor/github.com/containerd/containerd/services.go b/vendor/github.com/containerd/containerd/v2/client/services.go similarity index 77% rename from vendor/github.com/containerd/containerd/services.go rename to vendor/github.com/containerd/containerd/v2/client/services.go index edb8872e55..d2e69a1cee 100644 --- a/vendor/github.com/containerd/containerd/services.go +++ b/vendor/github.com/containerd/containerd/v2/client/services.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "fmt" @@ -22,19 +22,19 @@ import ( containersapi "github.com/containerd/containerd/api/services/containers/v1" "github.com/containerd/containerd/api/services/diff/v1" imagesapi "github.com/containerd/containerd/api/services/images/v1" - introspectionapi "github.com/containerd/containerd/api/services/introspection/v1" namespacesapi "github.com/containerd/containerd/api/services/namespaces/v1" "github.com/containerd/containerd/api/services/tasks/v1" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/sandbox" - srv "github.com/containerd/containerd/services" - "github.com/containerd/containerd/services/introspection" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/introspection" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/sandbox" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/plugins" + srv "github.com/containerd/containerd/v2/plugins/services" + "github.com/containerd/plugin" ) type services struct { @@ -49,7 +49,7 @@ type services struct { leasesService leases.Manager introspectionService introspection.Service sandboxStore sandbox.Store - sandboxController sandbox.Controller + sandboxers map[string]sandbox.Controller } // ServicesOpt allows callers to set options on the services @@ -149,13 +149,6 @@ func WithLeasesService(leasesService leases.Manager) ServicesOpt { } } -// WithIntrospectionClient sets the introspection service using an introspection client. -func WithIntrospectionClient(in introspectionapi.IntrospectionClient) ServicesOpt { - return func(s *services) { - s.introspectionService = introspection.NewIntrospectionServiceFromClient(in) - } -} - // WithIntrospectionService sets the introspection service. func WithIntrospectionService(in introspection.Service) ServicesOpt { return func(s *services) { @@ -170,40 +163,30 @@ func WithSandboxStore(client sandbox.Store) ServicesOpt { } } -// WithSandboxController sets the sandbox controller. -func WithSandboxController(client sandbox.Controller) ServicesOpt { - return func(s *services) { - s.sandboxController = client - } -} - // WithInMemoryServices is suitable for cases when there is need to use containerd's client from // another (in-memory) containerd plugin (such as CRI). -func WithInMemoryServices(ic *plugin.InitContext) ClientOpt { +func WithInMemoryServices(ic *plugin.InitContext) Opt { return func(c *clientOpts) error { var opts []ServicesOpt for t, fn := range map[plugin.Type]func(interface{}) ServicesOpt{ - plugin.EventPlugin: func(i interface{}) ServicesOpt { + plugins.EventPlugin: func(i interface{}) ServicesOpt { return WithEventService(i.(EventService)) }, - plugin.LeasePlugin: func(i interface{}) ServicesOpt { + plugins.LeasePlugin: func(i interface{}) ServicesOpt { return WithLeasesService(i.(leases.Manager)) }, - plugin.SandboxStorePlugin: func(i interface{}) ServicesOpt { + plugins.SandboxStorePlugin: func(i interface{}) ServicesOpt { return WithSandboxStore(i.(sandbox.Store)) }, - plugin.SandboxControllerPlugin: func(i interface{}) ServicesOpt { - return WithSandboxController(i.(sandbox.Controller)) - }, } { - i, err := ic.Get(t) + i, err := ic.GetSingle(t) if err != nil { return fmt.Errorf("failed to get %q plugin: %w", t, err) } opts = append(opts, fn(i)) } - plugins, err := ic.GetByType(plugin.ServicePlugin) + plugins, err := ic.GetByType(plugins.ServicePlugin) if err != nil { return fmt.Errorf("failed to get service plugin: %w", err) } @@ -230,19 +213,12 @@ func WithInMemoryServices(ic *plugin.InitContext) ClientOpt { return WithNamespaceClient(s.(namespacesapi.NamespacesClient)) }, srv.IntrospectionService: func(s interface{}) ServicesOpt { - return WithIntrospectionClient(s.(introspectionapi.IntrospectionClient)) + return WithIntrospectionService(s.(introspection.Service)) }, } { - p := plugins[s] - if p == nil { - return fmt.Errorf("service %q not found", s) - } - i, err := p.Instance() - if err != nil { - return fmt.Errorf("failed to get instance of service %q: %w", s, err) - } + i := plugins[s] if i == nil { - return fmt.Errorf("instance of service %q not found", s) + return fmt.Errorf("service %q not found", s) } opts = append(opts, fn(i)) } diff --git a/vendor/github.com/containerd/containerd/signals.go b/vendor/github.com/containerd/containerd/v2/client/signals.go similarity index 72% rename from vendor/github.com/containerd/containerd/signals.go rename to vendor/github.com/containerd/containerd/v2/client/signals.go index 9d81eed876..9488b22996 100644 --- a/vendor/github.com/containerd/containerd/signals.go +++ b/vendor/github.com/containerd/containerd/v2/client/signals.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package client import ( "context" @@ -22,8 +22,8 @@ import ( "fmt" "syscall" - "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/moby/sys/signal" v1 "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -57,37 +57,27 @@ func GetOCIStopSignal(ctx context.Context, image Image, defaultSignal string) (s if err != nil { return "", err } + if !images.IsConfigType(ic.MediaType) { + return "", fmt.Errorf("unknown image config media type %s", ic.MediaType) + } + var ( ociimage v1.Image config v1.ImageConfig ) - switch ic.MediaType { - case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config: - p, err := content.ReadBlob(ctx, image.ContentStore(), ic) - if err != nil { - return "", err - } - - if err := json.Unmarshal(p, &ociimage); err != nil { - return "", err - } - config = ociimage.Config - default: - return "", fmt.Errorf("unknown image config media type %s", ic.MediaType) + p, err := content.ReadBlob(ctx, image.ContentStore(), ic) + if err != nil { + return "", err } + if err = json.Unmarshal(p, &ociimage); err != nil { + return "", err + } + config = ociimage.Config + if config.StopSignal == "" { return defaultSignal, nil } return config.StopSignal, nil } - -// ParseSignal parses a given string into a syscall.Signal -// the rawSignal can be a string with "SIG" prefix, -// or a signal number in string format. -// -// Deprecated: Use github.com/moby/sys/signal instead. -func ParseSignal(rawSignal string) (syscall.Signal, error) { - return signal.ParseSignal(rawSignal) -} diff --git a/vendor/github.com/containerd/containerd/snapshotter_opts_unix.go b/vendor/github.com/containerd/containerd/v2/client/snapshotter_opts_unix.go similarity index 52% rename from vendor/github.com/containerd/containerd/snapshotter_opts_unix.go rename to vendor/github.com/containerd/containerd/v2/client/snapshotter_opts_unix.go index 4739e192fd..5984b2176d 100644 --- a/vendor/github.com/containerd/containerd/snapshotter_opts_unix.go +++ b/vendor/github.com/containerd/containerd/v2/client/snapshotter_opts_unix.go @@ -16,22 +16,28 @@ limitations under the License. */ -package containerd +package client import ( "context" + "encoding/json" "fmt" + "slices" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/internal/userns" + "github.com/opencontainers/go-digest" + "github.com/opencontainers/runtime-spec/specs-go" ) const ( - capabRemapIDs = "remap-ids" + capaRemapIDs = "remap-ids" + capaOnlyRemapIDs = "only-remap-ids" ) // WithRemapperLabels creates the labels used by any supporting snapshotter // to shift the filesystem ownership (user namespace mapping) automatically; currently -// supported by the fuse-overlayfs snapshotter +// supported by the fuse-overlayfs and overlay snapshotters func WithRemapperLabels(ctrUID, hostUID, ctrGID, hostGID, length uint32) snapshots.Opt { return snapshots.WithLabels(map[string]string{ snapshots.LabelSnapshotUIDMapping: fmt.Sprintf("%d:%d:%d", ctrUID, hostUID, length), @@ -45,7 +51,7 @@ func resolveSnapshotOptions(ctx context.Context, client *Client, snapshotterName } for _, capab := range capabs { - if capab == capabRemapIDs { + if capab == capaRemapIDs { // Snapshotter supports ID remapping, we don't need to do anything. return parent, nil } @@ -57,39 +63,58 @@ func resolveSnapshotOptions(ctx context.Context, client *Client, snapshotterName } needsRemap := false - var uidMap, gidMap string + var uidMapLabel, gidMapLabel string if value, ok := local.Labels[snapshots.LabelSnapshotUIDMapping]; ok { needsRemap = true - uidMap = value + uidMapLabel = value } if value, ok := local.Labels[snapshots.LabelSnapshotGIDMapping]; ok { needsRemap = true - gidMap = value + gidMapLabel = value } if !needsRemap { return parent, nil } - var ctrUID, hostUID, length uint32 - _, err = fmt.Sscanf(uidMap, "%d:%d:%d", &ctrUID, &hostUID, &length) + capaOnlyRemap := false + for _, capa := range capabs { + if capa == capaOnlyRemapIDs { + capaOnlyRemap = true + } + } + + if capaOnlyRemap { + return "", fmt.Errorf("snapshotter %q doesn't support idmap mounts on this host, configure `slow_chown` to allow a slower and expensive fallback", snapshotterName) + } + + var uidMap, gidMap specs.LinuxIDMapping + _, err = fmt.Sscanf(uidMapLabel, "%d:%d:%d", &uidMap.ContainerID, &uidMap.HostID, &uidMap.Size) if err != nil { - return "", fmt.Errorf("uidMap unparsable: %w", err) + return "", fmt.Errorf("uidMapLabel unparsable: %w", err) } - - var ctrGID, hostGID, lengthGID uint32 - _, err = fmt.Sscanf(gidMap, "%d:%d:%d", &ctrGID, &hostGID, &lengthGID) + _, err = fmt.Sscanf(gidMapLabel, "%d:%d:%d", &gidMap.ContainerID, &gidMap.HostID, &gidMap.Size) if err != nil { - return "", fmt.Errorf("gidMap unparsable: %w", err) + return "", fmt.Errorf("gidMapLabel unparsable: %w", err) } - if ctrUID != 0 || ctrGID != 0 { - return "", fmt.Errorf("Container UID/GID of 0 only supported currently (%d/%d)", ctrUID, ctrGID) + if uidMap.ContainerID != 0 || gidMap.ContainerID != 0 { + return "", fmt.Errorf("Container UID/GID of 0 only supported currently (%d/%d)", uidMap.ContainerID, gidMap.ContainerID) + } + + rsn := remappedSnapshot{ + Parent: parent, + IDMap: userns.IDMap{ + UidMap: []specs.LinuxIDMapping{uidMap}, + GidMap: []specs.LinuxIDMapping{gidMap}, + }, + } + usernsID, err := rsn.ID() + if err != nil { + return "", fmt.Errorf("failed to remap snapshot: %w", err) } - // TODO(dgl): length isn't taken into account for the intermediate snapshot id. - usernsID := fmt.Sprintf("%s-%d-%d", parent, hostUID, hostGID) if _, err := snapshotter.Stat(ctx, usernsID); err == nil { return usernsID, nil } @@ -97,8 +122,8 @@ func resolveSnapshotOptions(ctx context.Context, client *Client, snapshotterName if err != nil { return "", err } - // TODO(dgl): length isn't taken into account here yet either. - if err := remapRootFS(ctx, mounts, hostUID, hostGID); err != nil { + + if err := remapRootFS(ctx, mounts, rsn.IDMap); err != nil { snapshotter.Remove(ctx, usernsID+"-remap") return "", err } @@ -108,3 +133,27 @@ func resolveSnapshotOptions(ctx context.Context, client *Client, snapshotterName return usernsID, nil } + +type remappedSnapshot struct { + Parent string `json:"Parent"` + IDMap userns.IDMap `json:"IDMap"` +} + +func (s *remappedSnapshot) ID() (string, error) { + compare := func(a, b specs.LinuxIDMapping) int { + if a.ContainerID < b.ContainerID { + return -1 + } else if a.ContainerID == b.ContainerID { + return 0 + } + return 1 + } + slices.SortStableFunc(s.IDMap.UidMap, compare) + slices.SortStableFunc(s.IDMap.GidMap, compare) + + buf, err := json.Marshal(s) + if err != nil { + return "", err + } + return digest.FromBytes(buf).String(), nil +} diff --git a/vendor/github.com/containerd/containerd/snapshotter_opts_windows.go b/vendor/github.com/containerd/containerd/v2/client/snapshotter_opts_windows.go similarity index 92% rename from vendor/github.com/containerd/containerd/snapshotter_opts_windows.go rename to vendor/github.com/containerd/containerd/v2/client/snapshotter_opts_windows.go index 540bcb3130..ab78663c51 100644 --- a/vendor/github.com/containerd/containerd/snapshotter_opts_windows.go +++ b/vendor/github.com/containerd/containerd/v2/client/snapshotter_opts_windows.go @@ -14,12 +14,12 @@ limitations under the License. */ -package containerd +package client import ( "context" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/snapshots" ) func resolveSnapshotOptions(ctx context.Context, client *Client, snapshotterName string, snapshotter snapshots.Snapshotter, parent string, opts ...snapshots.Opt) (string, error) { diff --git a/vendor/github.com/containerd/containerd/task.go b/vendor/github.com/containerd/containerd/v2/client/task.go similarity index 84% rename from vendor/github.com/containerd/containerd/task.go rename to vendor/github.com/containerd/containerd/v2/client/task.go index aba9e57193..20312a922a 100644 --- a/vendor/github.com/containerd/containerd/task.go +++ b/vendor/github.com/containerd/containerd/v2/client/task.go @@ -14,12 +14,10 @@ limitations under the License. */ -package containerd +package client import ( - "bytes" "context" - "encoding/json" "errors" "fmt" "io" @@ -31,23 +29,25 @@ import ( "github.com/containerd/containerd/api/services/tasks/v1" "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types/runc/options" - "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/mount" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/plugin" - "github.com/containerd/containerd/protobuf" - google_protobuf "github.com/containerd/containerd/protobuf/types" - "github.com/containerd/containerd/rootfs" - "github.com/containerd/containerd/runtime/linux/runctypes" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" "github.com/containerd/typeurl/v2" digest "github.com/opencontainers/go-digest" is "github.com/opencontainers/image-spec/specs-go" v1 "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/runtime-spec/specs-go" + + "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/mount" + "github.com/containerd/containerd/v2/pkg/cio" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/containerd/v2/pkg/protobuf" + google_protobuf "github.com/containerd/containerd/v2/pkg/protobuf/types" + "github.com/containerd/containerd/v2/pkg/rootfs" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/containerd/v2/plugins" ) // UnknownExitStatus is returned when containerd is unable to @@ -213,6 +213,10 @@ func (t *task) Pid() uint32 { } func (t *task) Start(ctx context.Context) error { + ctx, span := tracing.StartSpan(ctx, "task.Start", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() r, err := t.client.TaskService().Start(ctx, &tasks.StartRequest{ ContainerID: t.id, }) @@ -221,19 +225,30 @@ func (t *task) Start(ctx context.Context) error { t.io.Cancel() t.io.Close() } - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } + span.SetAttributes(tracing.Attribute("task.pid", r.Pid)) t.pid = r.Pid return nil } func (t *task) Kill(ctx context.Context, s syscall.Signal, opts ...KillOpts) error { + ctx, span := tracing.StartSpan(ctx, "task.Kill", + tracing.WithAttribute("task.id", t.ID()), + tracing.WithAttribute("task.pid", int(t.Pid())), + ) + defer span.End() var i KillInfo for _, o := range opts { if err := o(ctx, &i); err != nil { return err } } + + span.SetAttributes( + tracing.Attribute("task.exec.id", i.ExecID), + tracing.Attribute("task.exec.killall", i.All), + ) _, err := t.client.TaskService().Kill(ctx, &tasks.KillRequest{ Signal: uint32(s), ContainerID: t.id, @@ -241,23 +256,31 @@ func (t *task) Kill(ctx context.Context, s syscall.Signal, opts ...KillOpts) err All: i.All, }) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } func (t *task) Pause(ctx context.Context) error { + ctx, span := tracing.StartSpan(ctx, "task.Pause", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() _, err := t.client.TaskService().Pause(ctx, &tasks.PauseTaskRequest{ ContainerID: t.id, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (t *task) Resume(ctx context.Context) error { + ctx, span := tracing.StartSpan(ctx, "task.Resume", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() _, err := t.client.TaskService().Resume(ctx, &tasks.ResumeTaskRequest{ ContainerID: t.id, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (t *task) Status(ctx context.Context) (Status, error) { @@ -265,12 +288,16 @@ func (t *task) Status(ctx context.Context) (Status, error) { ContainerID: t.id, }) if err != nil { - return Status{}, errdefs.FromGRPC(err) + return Status{}, errgrpc.ToNative(err) } + status := ProcessStatus(strings.ToLower(r.Process.Status.String())) + exitStatus := r.Process.ExitStatus + exitTime := protobuf.FromTimestamp(r.Process.ExitedAt) + return Status{ - Status: ProcessStatus(strings.ToLower(r.Process.Status.String())), - ExitStatus: r.Process.ExitStatus, - ExitTime: protobuf.FromTimestamp(r.Process.ExitedAt), + Status: status, + ExitStatus: exitStatus, + ExitTime: exitTime, }, nil } @@ -278,6 +305,10 @@ func (t *task) Wait(ctx context.Context) (<-chan ExitStatus, error) { c := make(chan ExitStatus, 1) go func() { defer close(c) + ctx, span := tracing.StartSpan(ctx, "task.Wait", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() r, err := t.client.TaskService().Wait(ctx, &tasks.WaitRequest{ ContainerID: t.id, }) @@ -300,6 +331,10 @@ func (t *task) Wait(ctx context.Context) (<-chan ExitStatus, error) { // it returns the exit status of the task and any errors that were encountered // during cleanup func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStatus, error) { + ctx, span := tracing.StartSpan(ctx, "task.Delete", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() for _, o := range opts { if err := o(ctx, t); err != nil { return nil, err @@ -309,10 +344,11 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat if err != nil && errdefs.IsNotFound(err) { return nil, err } + switch status.Status { case Stopped, Unknown, "": case Created: - if t.client.runtime == fmt.Sprintf("%s.%s", plugin.RuntimePlugin, "windows") { + if t.client.runtime == plugins.RuntimePlugin.String()+".windows" { // On windows Created is akin to Stopped break } @@ -329,7 +365,7 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat // io.Wait locks for restored tasks on Windows unless we call // io.Close first (https://github.com/containerd/containerd/issues/5621) // in other cases, preserve the contract and let IO finish before closing - if t.client.runtime == fmt.Sprintf("%s.%s", plugin.RuntimePlugin, "windows") { + if t.client.runtime == plugins.RuntimePlugin.String()+".windows" { t.io.Close() } // io.Cancel is used to cancel the io goroutine while it is in @@ -343,7 +379,7 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat ContainerID: t.id, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } // Only cleanup the IO after a successful Delete if t.io != nil { @@ -353,9 +389,14 @@ func (t *task) Delete(ctx context.Context, opts ...ProcessDeleteOpts) (*ExitStat } func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreate cio.Creator) (_ Process, err error) { + ctx, span := tracing.StartSpan(ctx, "task.Exec", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() if id == "" { return nil, fmt.Errorf("exec id must not be empty: %w", errdefs.ErrInvalidArgument) } + span.SetAttributes(tracing.Attribute("task.exec.id", id)) i, err := ioCreate(id) if err != nil { return nil, err @@ -366,7 +407,7 @@ func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreat i.Close() } }() - any, err := protobuf.MarshalAnyToProto(spec) + pSpec, err := typeurl.MarshalAnyToProto(spec) if err != nil { return nil, err } @@ -378,13 +419,13 @@ func (t *task) Exec(ctx context.Context, id string, spec *specs.Process, ioCreat Stdin: cfg.Stdin, Stdout: cfg.Stdout, Stderr: cfg.Stderr, - Spec: any, + Spec: pSpec, } if _, err := t.client.TaskService().Exec(ctx, request); err != nil { i.Cancel() i.Wait() i.Close() - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } return &process{ id: id, @@ -398,7 +439,7 @@ func (t *task) Pids(ctx context.Context) ([]ProcessInfo, error) { ContainerID: t.id, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } var processList []ProcessInfo for _, p := range response.Processes { @@ -411,6 +452,10 @@ func (t *task) Pids(ctx context.Context) ([]ProcessInfo, error) { } func (t *task) CloseIO(ctx context.Context, opts ...IOCloserOpts) error { + ctx, span := tracing.StartSpan(ctx, "task.CloseIO", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() r := &tasks.CloseIORequest{ ContainerID: t.id, } @@ -419,8 +464,9 @@ func (t *task) CloseIO(ctx context.Context, opts ...IOCloserOpts) error { o(&i) } r.Stdin = i.Stdin + _, err := t.client.TaskService().CloseIO(ctx, r) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (t *task) IO() cio.IO { @@ -428,12 +474,16 @@ func (t *task) IO() cio.IO { } func (t *task) Resize(ctx context.Context, w, h uint32) error { + ctx, span := tracing.StartSpan(ctx, "task.Resize", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() _, err := t.client.TaskService().ResizePty(ctx, &tasks.ResizePtyRequest{ ContainerID: t.id, Width: w, Height: h, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } // NOTE: Checkpoint supports to dump task information to a directory, in this way, an empty @@ -466,11 +516,11 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag } request.ParentCheckpoint = i.ParentCheckpoint.String() if i.Options != nil { - any, err := protobuf.MarshalAnyToProto(i.Options) + o, err := typeurl.MarshalAnyToProto(i.Options) if err != nil { return nil, err } - request.Options = any + request.Options = o } status, err := t.Status(ctx) @@ -512,7 +562,7 @@ func (t *task) Checkpoint(ctx context.Context, opts ...CheckpointTaskOpts) (Imag return nil, err } } - desc, err := t.writeIndex(ctx, &index) + desc, err := writeIndex(ctx, &index, t.client, t.id) if err != nil { return nil, err } @@ -541,6 +591,10 @@ type UpdateTaskInfo struct { type UpdateTaskOpts func(context.Context, *Client, *UpdateTaskInfo) error func (t *task) Update(ctx context.Context, opts ...UpdateTaskOpts) error { + ctx, span := tracing.StartSpan(ctx, "task.Update", + tracing.WithAttribute("task.id", t.ID()), + ) + defer span.End() request := &tasks.UpdateTaskRequest{ ContainerID: t.id, } @@ -551,17 +605,17 @@ func (t *task) Update(ctx context.Context, opts ...UpdateTaskOpts) error { } } if i.Resources != nil { - any, err := typeurl.MarshalAny(i.Resources) + r, err := typeurl.MarshalAny(i.Resources) if err != nil { return err } - request.Resources = protobuf.FromAny(any) + request.Resources = typeurl.MarshalProto(r) } if i.Annotations != nil { request.Annotations = i.Annotations } _, err := t.client.TaskService().Update(ctx, request) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (t *task) LoadProcess(ctx context.Context, id string, ioAttach cio.Attach) (Process, error) { @@ -573,7 +627,7 @@ func (t *task) LoadProcess(ctx context.Context, id string, ioAttach cio.Attach) ExecID: id, }) if err != nil { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) if errdefs.IsNotFound(err) { return nil, fmt.Errorf("no running process found: %w", err) } @@ -599,7 +653,7 @@ func (t *task) Metrics(ctx context.Context) (*types.Metric, error) { }, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } if response.Metrics == nil { @@ -616,7 +670,7 @@ func (t *task) Metrics(ctx context.Context) (*types.Metric, error) { func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tasks.CheckpointTaskRequest) error { response, err := t.client.TaskService().Checkpoint(ctx, request) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } // NOTE: response.Descriptors can be an empty slice if checkpoint image is jumped // add the checkpoint descriptors to the index @@ -663,18 +717,6 @@ func (t *task) checkpointImage(ctx context.Context, index *v1.Index, image strin return nil } -func (t *task) writeIndex(ctx context.Context, index *v1.Index) (d v1.Descriptor, err error) { - labels := map[string]string{} - for i, m := range index.Manifests { - labels[fmt.Sprintf("containerd.io/gc.ref.content.%d", i)] = m.Digest.String() - } - buf := bytes.NewBuffer(nil) - if err := json.NewEncoder(buf).Encode(index); err != nil { - return v1.Descriptor{}, err - } - return writeContent(ctx, t.client.ContentStore(), v1.MediaTypeImageIndex, t.id, buf, content.WithLabels(labels)) -} - func writeContent(ctx context.Context, store content.Ingester, mediaType, ref string, r io.Reader, opts ...content.Opt) (d v1.Descriptor, err error) { writer, err := store.Writer(ctx, content.WithRef(ref)) if err != nil { @@ -705,15 +747,10 @@ func isCheckpointPathExist(runtime string, v interface{}) bool { } switch runtime { - case plugin.RuntimeRuncV1, plugin.RuntimeRuncV2: + case plugins.RuntimeRuncV2: if opts, ok := v.(*options.CheckpointOptions); ok && opts.ImagePath != "" { return true } - - case plugin.RuntimeLinuxV1: - if opts, ok := v.(*runctypes.CheckpointOptions); ok && opts.ImagePath != "" { - return true - } } return false diff --git a/vendor/github.com/containerd/containerd/task_opts.go b/vendor/github.com/containerd/containerd/v2/client/task_opts.go similarity index 76% rename from vendor/github.com/containerd/containerd/task_opts.go rename to vendor/github.com/containerd/containerd/v2/client/task_opts.go index 87011b7bd1..8e94d4c597 100644 --- a/vendor/github.com/containerd/containerd/task_opts.go +++ b/vendor/github.com/containerd/containerd/v2/client/task_opts.go @@ -14,23 +14,19 @@ limitations under the License. */ -package containerd +package client import ( "context" - "encoding/json" "errors" "fmt" "syscall" "github.com/containerd/containerd/api/types" "github.com/containerd/containerd/api/types/runc/options" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/runtime/linux/runctypes" - imagespec "github.com/opencontainers/image-spec/specs-go/v1" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/errdefs" "github.com/opencontainers/runtime-spec/specs-go" ) @@ -54,6 +50,23 @@ func WithRuntimePath(absRuntimePath string) NewTaskOpts { } } +// WithTaskAPIEndpoint allow task service to manage a task through a given endpoint, +// usually it is served inside a sandbox, and we can get it from sandbox status. +func WithTaskAPIEndpoint(address string, version uint32) NewTaskOpts { + return func(ctx context.Context, client *Client, info *TaskInfo) error { + if info.Options == nil { + info.Options = &options.Options{} + } + opts, ok := info.Options.(*options.Options) + if !ok { + return errors.New("invalid runtime v2 options format") + } + opts.TaskApiAddress = address + opts.TaskApiVersion = version + return nil + } +} + // WithTaskCheckpoint allows a task to be created with live runtime and memory data from a // previous checkpoint. Additional software such as CRIU may be required to // restore a task from a checkpoint @@ -80,19 +93,6 @@ func WithTaskCheckpoint(im Image) NewTaskOpts { } } -func decodeIndex(ctx context.Context, store content.Provider, desc imagespec.Descriptor) (*imagespec.Index, error) { - var index imagespec.Index - p, err := content.ReadBlob(ctx, store, desc) - if err != nil { - return nil, err - } - if err := json.Unmarshal(p, &index); err != nil { - return nil, err - } - - return &index, nil -} - // WithCheckpointName sets the image name for the checkpoint func WithCheckpointName(name string) CheckpointTaskOpts { return func(r *CheckpointTaskInfo) error { @@ -104,25 +104,14 @@ func WithCheckpointName(name string) CheckpointTaskOpts { // WithCheckpointImagePath sets image path for checkpoint option func WithCheckpointImagePath(path string) CheckpointTaskOpts { return func(r *CheckpointTaskInfo) error { - if CheckRuntime(r.Runtime(), "io.containerd.runc") { - if r.Options == nil { - r.Options = &options.CheckpointOptions{} - } - opts, ok := r.Options.(*options.CheckpointOptions) - if !ok { - return errors.New("invalid v2 shim checkpoint options format") - } - opts.ImagePath = path - } else { - if r.Options == nil { - r.Options = &runctypes.CheckpointOptions{} - } - opts, ok := r.Options.(*runctypes.CheckpointOptions) - if !ok { - return errors.New("invalid v1 shim checkpoint options format") - } - opts.ImagePath = path + if r.Options == nil { + r.Options = &options.CheckpointOptions{} } + opts, ok := r.Options.(*options.CheckpointOptions) + if !ok { + return errors.New("invalid runtime v2 checkpoint options format") + } + opts.ImagePath = path return nil } } @@ -130,25 +119,29 @@ func WithCheckpointImagePath(path string) CheckpointTaskOpts { // WithRestoreImagePath sets image path for create option func WithRestoreImagePath(path string) NewTaskOpts { return func(ctx context.Context, c *Client, ti *TaskInfo) error { - if CheckRuntime(ti.Runtime(), "io.containerd.runc") { - if ti.Options == nil { - ti.Options = &options.Options{} - } - opts, ok := ti.Options.(*options.Options) - if !ok { - return errors.New("invalid v2 shim create options format") - } - opts.CriuImagePath = path - } else { - if ti.Options == nil { - ti.Options = &runctypes.CreateOptions{} - } - opts, ok := ti.Options.(*runctypes.CreateOptions) - if !ok { - return errors.New("invalid v1 shim create options format") - } - opts.CriuImagePath = path + if ti.Options == nil { + ti.Options = &options.Options{} } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid runtime v2 options format") + } + opts.CriuImagePath = path + return nil + } +} + +// WithRestoreWorkPath sets criu work path for create option +func WithRestoreWorkPath(path string) NewTaskOpts { + return func(ctx context.Context, c *Client, ti *TaskInfo) error { + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid runtime v2 options format") + } + opts.CriuWorkPath = path return nil } } diff --git a/vendor/github.com/containerd/containerd/v2/client/task_opts_unix.go b/vendor/github.com/containerd/containerd/v2/client/task_opts_unix.go new file mode 100644 index 0000000000..d33e30284e --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/client/task_opts_unix.go @@ -0,0 +1,98 @@ +//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 client + +import ( + "context" + "errors" + + "github.com/containerd/containerd/api/types/runc/options" +) + +// WithNoNewKeyring causes tasks not to be created with a new keyring for secret storage. +// There is an upper limit on the number of keyrings in a linux system +func WithNoNewKeyring(ctx context.Context, c *Client, ti *TaskInfo) error { + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid v2 shim create options format") + } + opts.NoNewKeyring = true + return nil +} + +// WithNoPivotRoot instructs the runtime not to you pivot_root +func WithNoPivotRoot(_ context.Context, _ *Client, ti *TaskInfo) error { + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid v2 shim create options format") + } + opts.NoPivotRoot = true + return nil +} + +// WithShimCgroup sets the existing cgroup for the shim +func WithShimCgroup(path string) NewTaskOpts { + return func(ctx context.Context, c *Client, ti *TaskInfo) error { + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid v2 shim create options format") + } + opts.ShimCgroup = path + return nil + } +} + +// WithUIDOwner allows console I/O to work with the remapped UID in user namespace +func WithUIDOwner(uid uint32) NewTaskOpts { + return func(ctx context.Context, c *Client, ti *TaskInfo) error { + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid v2 shim create options format") + } + opts.IoUid = uid + return nil + } +} + +// WithGIDOwner allows console I/O to work with the remapped GID in user namespace +func WithGIDOwner(gid uint32) NewTaskOpts { + return func(ctx context.Context, c *Client, ti *TaskInfo) error { + if ti.Options == nil { + ti.Options = &options.Options{} + } + opts, ok := ti.Options.(*options.Options) + if !ok { + return errors.New("invalid v2 shim create options format") + } + opts.IoGid = gid + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/v2/client/transfer.go b/vendor/github.com/containerd/containerd/v2/client/transfer.go new file mode 100644 index 0000000000..5bd02aa6d2 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/client/transfer.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 client + +import ( + "context" + + "github.com/containerd/containerd/v2/core/streaming" + streamproxy "github.com/containerd/containerd/v2/core/streaming/proxy" + "github.com/containerd/containerd/v2/core/transfer" + "github.com/containerd/containerd/v2/core/transfer/proxy" +) + +func (c *Client) Transfer(ctx context.Context, src interface{}, dest interface{}, opts ...transfer.Opt) error { + ctx, done, err := c.WithLease(ctx) + if err != nil { + return err + } + defer done(ctx) + + return proxy.NewTransferrer(c.conn, c.streamCreator()).Transfer(ctx, src, dest, opts...) +} + +func (c *Client) streamCreator() streaming.StreamCreator { + return streamproxy.NewStreamCreator(c.conn) +} diff --git a/vendor/github.com/containerd/containerd/services/server/config/config.go b/vendor/github.com/containerd/containerd/v2/cmd/containerd/server/config/config.go similarity index 51% rename from vendor/github.com/containerd/containerd/services/server/config/config.go rename to vendor/github.com/containerd/containerd/v2/cmd/containerd/server/config/config.go index e3fac1d821..b9aacf6fea 100644 --- a/vendor/github.com/containerd/containerd/services/server/config/config.go +++ b/vendor/github.com/containerd/containerd/v2/cmd/containerd/server/config/config.go @@ -14,21 +14,41 @@ limitations under the License. */ +// config is the global configuration for containerd +// +// Version History +// 1: Deprecated and removed in containerd 2.0 +// 2: Uses fully qualified plugin names +// 3: Added support for migration and warning on unknown fields package config import ( + "bytes" + "context" + "errors" "fmt" + "io" + "os" "path/filepath" + "reflect" "strings" "dario.cat/mergo" - "github.com/pelletier/go-toml" - "github.com/sirupsen/logrus" + "github.com/pelletier/go-toml/v2" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/plugin" + "github.com/containerd/containerd/v2/version" + "github.com/containerd/errdefs" + "github.com/containerd/log" + "github.com/containerd/plugin" ) +// migrations hold the migration functions for every prior containerd config version +var migrations = []func(context.Context, *Config) error{ + nil, // Version 0 is not defined, treated at version 1 + v1Migrate, // Version 1 plugins renamed to URI for version 2 + nil, // Version 2 has only plugin changes to version 3 +} + // NOTE: Any new map fields added also need to be handled in mergeConfig. // Config provides containerd configuration data for the server @@ -42,6 +62,8 @@ type Config struct { // TempDir is the path to a directory where to place containerd temporary files TempDir string `toml:"temp"` // PluginDir is the directory for dynamic plugins to be stored + // + // Deprecated: Please use proxy or binary external plugins. PluginDir string `toml:"plugin_dir"` // GRPC configuration settings GRPC GRPCConfig `toml:"grpc"` @@ -53,12 +75,14 @@ type Config struct { Metrics MetricsConfig `toml:"metrics"` // DisabledPlugins are IDs of plugins to disable. Disabled plugins won't be // initialized and started. + // DisabledPlugins must use a fully qualified plugin URI. DisabledPlugins []string `toml:"disabled_plugins"` // RequiredPlugins are IDs of required plugins. Containerd exits if any // required plugin doesn't exist or fails to be initialized or started. + // RequiredPlugins must use a fully qualified plugin URI. RequiredPlugins []string `toml:"required_plugins"` // Plugins provides plugin specific configuration for the initialization of a plugin - Plugins map[string]toml.Tree `toml:"plugins"` + Plugins map[string]interface{} `toml:"plugins"` // OOMScore adjust the containerd's oom score OOMScore int `toml:"oom_score"` // Cgroup specifies cgroup information for the containerd daemon process @@ -87,43 +111,98 @@ type StreamProcessor struct { Env []string `toml:"env"` } -// GetVersion returns the config file's version -func (c *Config) GetVersion() int { - if c.Version == 0 { - return 1 +// ValidateVersion validates the config for a v2 file +func (c *Config) ValidateVersion() error { + if c.Version > version.ConfigVersion { + return fmt.Errorf("expected containerd config version equal to or less than `%d`, got `%d`", version.ConfigVersion, c.Version) } - return c.Version -} -// ValidateV2 validates the config for a v2 file -func (c *Config) ValidateV2() error { - version := c.GetVersion() - if version < 2 { - logrus.Warnf("containerd config version `%d` has been deprecated and will be converted on each startup in containerd v2.0, "+ - "use `containerd config migrate` after upgrading to containerd 2.0 to avoid conversion on startup", version) - return nil - } - if version > 2 { - logrus.Errorf("containerd config version `%d` is not supported, the max version is `2`, "+ - "use `containerd config default` to generate a new config or manually revert to version `2`", version) - return fmt.Errorf("unsupported config version `%d`", version) - - } for _, p := range c.DisabledPlugins { - if !strings.HasPrefix(p, "io.containerd.") || len(strings.SplitN(p, ".", 4)) < 4 { + if !strings.ContainsAny(p, ".") { return fmt.Errorf("invalid disabled plugin URI %q expect io.containerd.x.vx", p) } } for _, p := range c.RequiredPlugins { - if !strings.HasPrefix(p, "io.containerd.") || len(strings.SplitN(p, ".", 4)) < 4 { + if !strings.ContainsAny(p, ".") { return fmt.Errorf("invalid required plugin URI %q expect io.containerd.x.vx", p) } } - for p := range c.Plugins { - if !strings.HasPrefix(p, "io.containerd.") || len(strings.SplitN(p, ".", 4)) < 4 { - return fmt.Errorf("invalid plugin key URI %q expect io.containerd.x.vx", p) + + return nil +} + +// MigrateConfig will convert the config to the latest version before using +func (c *Config) MigrateConfig(ctx context.Context) error { + return c.MigrateConfigTo(ctx, version.ConfigVersion) +} + +// MigrateConfigTo will convert the config to the target version before using +func (c *Config) MigrateConfigTo(ctx context.Context, targetVersion int) error { + for c.Version < targetVersion { + if m := migrations[c.Version]; m != nil { + if err := m(ctx, c); err != nil { + return err + } + } + c.Version++ + } + return nil +} + +func v1MigratePluginName(ctx context.Context, plugin string) string { + // corePlugins is the list of used plugins before v1 was deprecated + corePlugins := map[string]string{ + "cri": "io.containerd.grpc.v1.cri", + "cgroups": "io.containerd.monitor.v1.cgroups", + "linux": "io.containerd.runtime.v1.linux", + "scheduler": "io.containerd.gc.v1.scheduler", + "bolt": "io.containerd.metadata.v1.bolt", + "task": "io.containerd.runtime.v2.task", + "opt": "io.containerd.internal.v1.opt", + "restart": "io.containerd.internal.v1.restart", + "tracing": "io.containerd.internal.v1.tracing", + "otlp": "io.containerd.tracing.processor.v1.otlp", + "aufs": "io.containerd.snapshotter.v1.aufs", + "btrfs": "io.containerd.snapshotter.v1.btrfs", + "devmapper": "io.containerd.snapshotter.v1.devmapper", + "native": "io.containerd.snapshotter.v1.native", + "overlayfs": "io.containerd.snapshotter.v1.overlayfs", + "zfs": "io.containerd.snapshotter.v1.zfs", + } + if !strings.ContainsAny(plugin, ".") { + var ambiguous string + if full, ok := corePlugins[plugin]; ok { + plugin = full + } else if strings.HasSuffix(plugin, "-service") { + plugin = "io.containerd.service.v1." + plugin + } else if plugin == "windows" || plugin == "windows-lcow" { + // runtime, differ, and snapshotter plugins do not have configs for v1 + ambiguous = plugin + plugin = "io.containerd.snapshotter.v1." + plugin + } else { + ambiguous = plugin + plugin = "io.containerd.grpc.v1." + plugin + } + if ambiguous != "" { + log.G(ctx).Warnf("Ambiguous %s plugin in v1 config, treating as %s", ambiguous, plugin) } } + return plugin +} + +func v1Migrate(ctx context.Context, c *Config) error { + plugins := make(map[string]interface{}, len(c.Plugins)) + for plugin, value := range c.Plugins { + plugins[v1MigratePluginName(ctx, plugin)] = value + } + c.Plugins = plugins + for i, plugin := range c.DisabledPlugins { + c.DisabledPlugins[i] = v1MigratePluginName(ctx, plugin) + } + for i, plugin := range c.RequiredPlugins { + c.RequiredPlugins[i] = v1MigratePluginName(ctx, plugin) + } + // No change in c.ProxyPlugins return nil } @@ -178,23 +257,39 @@ type ProxyPlugin struct { } // Decode unmarshals a plugin specific configuration by plugin id -func (c *Config) Decode(p *plugin.Registration) (interface{}, error) { - id := p.URI() - if c.GetVersion() == 1 { - id = p.ID - } +func (c *Config) Decode(ctx context.Context, id string, config interface{}) (interface{}, error) { data, ok := c.Plugins[id] if !ok { - return p.Config, nil + return config, nil } - if err := data.Unmarshal(p.Config); err != nil { + + b, err := toml.Marshal(data) + if err != nil { return nil, err } - return p.Config, nil + + if err := toml.NewDecoder(bytes.NewReader(b)).DisallowUnknownFields().Decode(config); err != nil { + var serr *toml.StrictMissingError + if errors.As(err, &serr) { + for _, derr := range serr.Errors { + log.G(ctx).WithFields(log.Fields{ + "plugin": id, + "key": strings.Join(derr.Key(), " "), + }).WithError(err).Warn("Ignoring unknown key in TOML for plugin") + } + err = toml.Unmarshal(b, config) + } + if err != nil { + return nil, err + } + + } + + return config, nil } // LoadConfig loads the containerd server config from the provided path -func LoadConfig(path string, out *Config) error { +func LoadConfig(ctx context.Context, path string, out *Config) error { if out == nil { return fmt.Errorf("argument out must not be nil: %w", errdefs.ErrInvalidArgument) } @@ -212,11 +307,20 @@ func LoadConfig(path string, out *Config) error { continue } - config, err := loadConfigFile(path) + config, err := loadConfigFile(ctx, path) if err != nil { return err } + switch config.Version { + case 0, 1: + if err := config.MigrateConfigTo(ctx, out.Version); err != nil { + return err + } + default: + // NOP + } + if err := mergeConfig(out, config); err != nil { return err } @@ -230,13 +334,7 @@ func LoadConfig(path string, out *Config) error { pending = append(pending, imports...) } - // Fix up the list of config files loaded - out.Imports = []string{} - for path := range loaded { - out.Imports = append(out.Imports, path) - } - - err := out.ValidateV2() + err := out.ValidateVersion() if err != nil { return fmt.Errorf("failed to load TOML from %s: %w", path, err) } @@ -244,30 +342,63 @@ func LoadConfig(path string, out *Config) error { } // loadConfigFile decodes a TOML file at the given path -func loadConfigFile(path string) (*Config, error) { +func loadConfigFile(ctx context.Context, path string) (*Config, error) { config := &Config{} - file, err := toml.LoadFile(path) + f, err := os.Open(path) if err != nil { - return nil, fmt.Errorf("failed to load TOML: %s: %w", path, err) + return nil, err } + defer f.Close() + + if err := toml.NewDecoder(f).DisallowUnknownFields().Decode(config); err != nil { + var serr *toml.StrictMissingError + if errors.As(err, &serr) { + for _, derr := range serr.Errors { + row, col := derr.Position() + log.G(ctx).WithFields(log.Fields{ + "file": path, + "row": row, + "column": col, + "key": strings.Join(derr.Key(), " "), + }).WithError(err).Warn("Ignoring unknown key in TOML") + } + + // Try decoding again with unknown fields + config = &Config{} + if _, seekerr := f.Seek(0, io.SeekStart); seekerr != nil { + return nil, fmt.Errorf("unable to seek file to start %w: failed to unmarshal TOML with unknown fields: %w", seekerr, err) + } + err = toml.NewDecoder(f).Decode(config) + } + if err != nil { + var derr *toml.DecodeError + if errors.As(err, &derr) { + row, column := derr.Position() + log.G(ctx).WithFields(log.Fields{ + "file": path, + "row": row, + "column": column, + }).WithError(err).Error("Failure unmarshaling TOML") + return nil, fmt.Errorf("failed to unmarshal TOML at row %d column %d: %w", row, column, err) + } + return nil, fmt.Errorf("failed to unmarshal TOML: %w", err) + } - if err := file.Unmarshal(config); err != nil { - return nil, fmt.Errorf("failed to unmarshal TOML: %w", err) } return config, nil } // resolveImports resolves import strings list to absolute paths list: -// - Non abs path is relative to parent config file directory // - If path contains *, glob pattern matching applied +// - Non abs path is relative to parent config file directory // - Abs paths returned as is func resolveImports(parent string, imports []string) ([]string, error) { var out []string for _, path := range imports { - path := filepath.Clean(path) + path = filepath.Clean(path) if !filepath.IsAbs(path) { path = filepath.Join(filepath.Dir(parent), path) } @@ -295,18 +426,16 @@ func resolveImports(parent string, imports []string) ([]string, error) { // 0 1 1 // []{"1"} []{"2"} []{"1","2"} // []{"1"} []{} []{"1"} +// []{"1", "2"} []{"1"} []{"1","2"} +// []{} []{"2"} []{"2"} // Maps merged by keys, but values are replaced entirely. func mergeConfig(to, from *Config) error { - err := mergo.Merge(to, from, mergo.WithOverride, mergo.WithAppendSlice) + err := mergo.Merge(to, from, mergo.WithOverride, mergo.WithTransformers(sliceTransformer{})) if err != nil { return err } // Replace entire sections instead of merging map's values. - for k, v := range from.Plugins { - to.Plugins[k] = v - } - for k, v := range from.StreamProcessors { to.StreamProcessors[k] = v } @@ -322,15 +451,40 @@ func mergeConfig(to, from *Config) error { return nil } -// V1DisabledFilter matches based on ID -func V1DisabledFilter(list []string) plugin.DisableFilter { - set := make(map[string]struct{}, len(list)) - for _, l := range list { - set[l] = struct{}{} +type sliceTransformer struct{} + +func (sliceTransformer) Transformer(t reflect.Type) func(dst, src reflect.Value) error { + if t.Kind() != reflect.Slice { + return nil } - return func(r *plugin.Registration) bool { - _, ok := set[r.ID] - return ok + return func(dst, src reflect.Value) error { + if !dst.CanSet() { + return nil + } + if src.Type() != dst.Type() { + return fmt.Errorf("cannot append two slice with different type (%s, %s)", src.Type(), dst.Type()) + } + for i := 0; i < src.Len(); i++ { + found := false + for j := 0; j < dst.Len(); j++ { + srcv := src.Index(i) + dstv := dst.Index(j) + if !srcv.CanInterface() || !dstv.CanInterface() { + if srcv.Equal(dstv) { + found = true + break + } + } else if reflect.DeepEqual(srcv.Interface(), dstv.Interface()) { + found = true + break + } + } + if !found { + dst.Set(reflect.Append(dst, src.Index(i))) + } + } + + return nil } } diff --git a/vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go b/vendor/github.com/containerd/containerd/v2/contrib/nvidia/nvidia.go similarity index 96% rename from vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go rename to vendor/github.com/containerd/containerd/v2/contrib/nvidia/nvidia.go index d08044aa20..7af06abf9f 100644 --- a/vendor/github.com/containerd/containerd/contrib/nvidia/nvidia.go +++ b/vendor/github.com/containerd/containerd/v2/contrib/nvidia/nvidia.go @@ -24,8 +24,8 @@ import ( "strconv" "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" specs "github.com/opencontainers/runtime-spec/specs-go" ) @@ -87,7 +87,7 @@ func WithGPUs(opts ...Opts) oci.SpecOpts { if s.Hooks == nil { s.Hooks = &specs.Hooks{} } - s.Hooks.Prestart = append(s.Hooks.Prestart, specs.Hook{ + s.Hooks.CreateRuntime = append(s.Hooks.CreateRuntime, specs.Hook{ Path: c.OCIHookPath, Args: append([]string{ "containerd", diff --git a/vendor/github.com/containerd/containerd/containers/containers.go b/vendor/github.com/containerd/containerd/v2/core/containers/containers.go similarity index 100% rename from vendor/github.com/containerd/containerd/containers/containers.go rename to vendor/github.com/containerd/containerd/v2/core/containers/containers.go diff --git a/vendor/github.com/containerd/containerd/content/adaptor.go b/vendor/github.com/containerd/containerd/v2/core/content/adaptor.go similarity index 96% rename from vendor/github.com/containerd/containerd/content/adaptor.go rename to vendor/github.com/containerd/containerd/v2/core/content/adaptor.go index 88bad2610e..4ba6cc74d3 100644 --- a/vendor/github.com/containerd/containerd/content/adaptor.go +++ b/vendor/github.com/containerd/containerd/v2/core/content/adaptor.go @@ -19,7 +19,7 @@ package content import ( "strings" - "github.com/containerd/containerd/filters" + "github.com/containerd/containerd/v2/pkg/filters" ) // AdaptInfo returns `filters.Adaptor` that handles `content.Info`. diff --git a/vendor/github.com/containerd/containerd/content/content.go b/vendor/github.com/containerd/containerd/v2/core/content/content.go similarity index 98% rename from vendor/github.com/containerd/containerd/content/content.go rename to vendor/github.com/containerd/containerd/v2/core/content/content.go index 2dc7bf8b52..66b42a9cb9 100644 --- a/vendor/github.com/containerd/containerd/content/content.go +++ b/vendor/github.com/containerd/containerd/v2/core/content/content.go @@ -165,6 +165,11 @@ type Writer interface { Truncate(size int64) error } +type Syncer interface { + // Sync flushes the in-flight writes to the disk (when applicable) + Sync() error +} + // Opt is used to alter the mutable properties of content type Opt func(*Info) error diff --git a/vendor/github.com/containerd/containerd/content/helpers.go b/vendor/github.com/containerd/containerd/v2/core/content/helpers.go similarity index 89% rename from vendor/github.com/containerd/containerd/content/helpers.go rename to vendor/github.com/containerd/containerd/v2/core/content/helpers.go index 93bcdde106..74cb566b02 100644 --- a/vendor/github.com/containerd/containerd/content/helpers.go +++ b/vendor/github.com/containerd/containerd/v2/core/content/helpers.go @@ -17,6 +17,7 @@ package content import ( + "bytes" "context" "errors" "fmt" @@ -24,12 +25,11 @@ import ( "sync" "time" + "github.com/containerd/containerd/v2/internal/randutil" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/pkg/randutil" ) var ErrReset = errors.New("writer has been reset") @@ -53,6 +53,31 @@ func NewReader(ra ReaderAt) io.Reader { return io.NewSectionReader(ra, 0, ra.Size()) } +type nopCloserBytesReader struct { + *bytes.Reader +} + +func (*nopCloserBytesReader) Close() error { return nil } + +type nopCloserSectionReader struct { + *io.SectionReader +} + +func (*nopCloserSectionReader) Close() error { return nil } + +// BlobReadSeeker returns a read seeker for the blob from the provider. +func BlobReadSeeker(ctx context.Context, provider Provider, desc ocispec.Descriptor) (io.ReadSeekCloser, error) { + if int64(len(desc.Data)) == desc.Size && digest.FromBytes(desc.Data) == desc.Digest { + return &nopCloserBytesReader{bytes.NewReader(desc.Data)}, nil + } + + ra, err := provider.ReaderAt(ctx, desc) + if err != nil { + return nil, err + } + return &nopCloserSectionReader{io.NewSectionReader(ra, 0, ra.Size())}, nil +} + // ReadBlob retrieves the entire contents of the blob from the provider. // // Avoid using this for large blobs, such as layers. @@ -146,32 +171,28 @@ func OpenWriter(ctx context.Context, cs Ingester, opts ...WriterOpt) (Writer, er // // Copy is buffered, so no need to wrap reader in buffered io. func Copy(ctx context.Context, cw Writer, or io.Reader, size int64, expected digest.Digest, opts ...Opt) error { - ws, err := cw.Status() - if err != nil { - return fmt.Errorf("failed to get status: %w", err) - } r := or - if ws.Offset > 0 { - r, err = seekReader(or, ws.Offset, size) - if err != nil { - return fmt.Errorf("unable to resume write to %v: %w", ws.Ref, err) - } - } - for i := 0; ; i++ { if i >= 1 { log.G(ctx).WithField("digest", expected).Debugf("retrying copy due to reset") } - copied, err := copyWithBuffer(cw, r) - if errors.Is(err, ErrReset) { - ws, err := cw.Status() - if err != nil { - return fmt.Errorf("failed to get status: %w", err) - } + + ws, err := cw.Status() + if err != nil { + return fmt.Errorf("failed to get status: %w", err) + } + // Reset the original reader if + // 1. there is an offset, or + // 2. this is a retry due to Reset error + if ws.Offset > 0 || i > 0 { r, err = seekReader(or, ws.Offset, size) if err != nil { return fmt.Errorf("unable to resume write to %v: %w", ws.Ref, err) } + } + + copied, err := copyWithBuffer(cw, r) + if errors.Is(err, ErrReset) { continue } if err != nil { @@ -183,14 +204,6 @@ func Copy(ctx context.Context, cw Writer, or io.Reader, size int64, expected dig } if err := cw.Commit(ctx, size, expected, opts...); err != nil { if errors.Is(err, ErrReset) { - ws, err := cw.Status() - if err != nil { - return fmt.Errorf("failed to get status: %w", err) - } - r, err = seekReader(or, ws.Offset, size) - if err != nil { - return fmt.Errorf("unable to resume write to %v: %w", ws.Ref, err) - } continue } if !errdefs.IsAlreadyExists(err) { diff --git a/vendor/github.com/containerd/containerd/content/proxy/content_reader.go b/vendor/github.com/containerd/containerd/v2/core/content/proxy/content_reader.go similarity index 97% rename from vendor/github.com/containerd/containerd/content/proxy/content_reader.go rename to vendor/github.com/containerd/containerd/v2/core/content/proxy/content_reader.go index 893e3b0f23..b591a7749d 100644 --- a/vendor/github.com/containerd/containerd/content/proxy/content_reader.go +++ b/vendor/github.com/containerd/containerd/v2/core/content/proxy/content_reader.go @@ -27,7 +27,7 @@ type remoteReaderAt struct { ctx context.Context digest digest.Digest size int64 - client contentapi.ContentClient + client contentapi.TTRPCContentClient } func (ra *remoteReaderAt) Size() int64 { diff --git a/vendor/github.com/containerd/containerd/content/proxy/content_store.go b/vendor/github.com/containerd/containerd/v2/core/content/proxy/content_store.go similarity index 60% rename from vendor/github.com/containerd/containerd/content/proxy/content_store.go rename to vendor/github.com/containerd/containerd/v2/core/content/proxy/content_store.go index 8e7fb42cf0..1c1c1cfc86 100644 --- a/vendor/github.com/containerd/containerd/content/proxy/content_store.go +++ b/vendor/github.com/containerd/containerd/v2/core/content/proxy/content_store.go @@ -18,26 +18,51 @@ package proxy import ( "context" + "fmt" "io" contentapi "github.com/containerd/containerd/api/services/content/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/protobuf" - protobuftypes "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/ttrpc" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/emptypb" + + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/protobuf" + protobuftypes "github.com/containerd/containerd/v2/pkg/protobuf/types" ) type proxyContentStore struct { - client contentapi.ContentClient + // client is the rpc content client + // NOTE: ttrpc is used because it is the smaller interface shared with grpc + client contentapi.TTRPCContentClient } // NewContentStore returns a new content store which communicates over a GRPC // connection using the containerd content GRPC API. -func NewContentStore(client contentapi.ContentClient) content.Store { - return &proxyContentStore{ - client: client, +func NewContentStore(client any) content.Store { + switch c := client.(type) { + case contentapi.ContentClient: + return &proxyContentStore{ + client: convertClient{c}, + } + case grpc.ClientConnInterface: + return &proxyContentStore{ + client: convertClient{contentapi.NewContentClient(c)}, + } + case contentapi.TTRPCContentClient: + return &proxyContentStore{ + client: c, + } + case *ttrpc.Client: + return &proxyContentStore{ + client: contentapi.NewTTRPCContentClient(c), + } + default: + panic(fmt.Errorf("unsupported content client %T: %w", client, errdefs.ErrNotImplemented)) } } @@ -46,7 +71,7 @@ func (pcs *proxyContentStore) Info(ctx context.Context, dgst digest.Digest) (con Digest: dgst.String(), }) if err != nil { - return content.Info{}, errdefs.FromGRPC(err) + return content.Info{}, errgrpc.ToNative(err) } return infoFromGRPC(resp.Info), nil @@ -57,14 +82,14 @@ func (pcs *proxyContentStore) Walk(ctx context.Context, fn content.WalkFunc, fil Filters: filters, }) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } for { msg, err := session.Recv() if err != nil { if err != io.EOF { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } break @@ -84,7 +109,7 @@ func (pcs *proxyContentStore) Delete(ctx context.Context, dgst digest.Digest) er if _, err := pcs.client.Delete(ctx, &contentapi.DeleteContentRequest{ Digest: dgst.String(), }); err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil @@ -110,7 +135,7 @@ func (pcs *proxyContentStore) Status(ctx context.Context, ref string) (content.S Ref: ref, }) if err != nil { - return content.Status{}, errdefs.FromGRPC(err) + return content.Status{}, errgrpc.ToNative(err) } status := resp.Status @@ -132,7 +157,7 @@ func (pcs *proxyContentStore) Update(ctx context.Context, info content.Info, fie }, }) if err != nil { - return content.Info{}, errdefs.FromGRPC(err) + return content.Info{}, errgrpc.ToNative(err) } return infoFromGRPC(resp.Info), nil } @@ -142,7 +167,7 @@ func (pcs *proxyContentStore) ListStatuses(ctx context.Context, filters ...strin Filters: filters, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } var statuses []content.Status @@ -170,7 +195,7 @@ func (pcs *proxyContentStore) Writer(ctx context.Context, opts ...content.Writer } wrclient, offset, err := pcs.negotiate(ctx, wOpts.Ref, wOpts.Desc.Size, wOpts.Desc.Digest) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } return &remoteWriter{ @@ -185,13 +210,13 @@ func (pcs *proxyContentStore) Abort(ctx context.Context, ref string) error { if _, err := pcs.client.Abort(ctx, &contentapi.AbortRequest{ Ref: ref, }); err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } -func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size int64, expected digest.Digest) (contentapi.Content_WriteClient, int64, error) { +func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size int64, expected digest.Digest) (contentapi.TTRPCContent_WriteClient, int64, error) { wrclient, err := pcs.client.Write(ctx) if err != nil { return nil, 0, err @@ -214,6 +239,70 @@ func (pcs *proxyContentStore) negotiate(ctx context.Context, ref string, size in return wrclient, resp.Offset, nil } +type convertClient struct { + contentapi.ContentClient +} + +func (c convertClient) Info(ctx context.Context, req *contentapi.InfoRequest) (*contentapi.InfoResponse, error) { + return c.ContentClient.Info(ctx, req) +} + +func (c convertClient) Update(ctx context.Context, req *contentapi.UpdateRequest) (*contentapi.UpdateResponse, error) { + return c.ContentClient.Update(ctx, req) +} + +type convertListClient struct { + contentapi.Content_ListClient +} + +func (c convertClient) List(ctx context.Context, req *contentapi.ListContentRequest) (contentapi.TTRPCContent_ListClient, error) { + lc, err := c.ContentClient.List(ctx, req) + if lc == nil { + return nil, err + } + return convertListClient{lc}, err +} + +func (c convertClient) Delete(ctx context.Context, req *contentapi.DeleteContentRequest) (*emptypb.Empty, error) { + return c.ContentClient.Delete(ctx, req) +} + +type convertReadClient struct { + contentapi.Content_ReadClient +} + +func (c convertClient) Read(ctx context.Context, req *contentapi.ReadContentRequest) (contentapi.TTRPCContent_ReadClient, error) { + rc, err := c.ContentClient.Read(ctx, req) + if rc == nil { + return nil, err + } + return convertReadClient{rc}, err +} + +func (c convertClient) Status(ctx context.Context, req *contentapi.StatusRequest) (*contentapi.StatusResponse, error) { + return c.ContentClient.Status(ctx, req) +} + +func (c convertClient) ListStatuses(ctx context.Context, req *contentapi.ListStatusesRequest) (*contentapi.ListStatusesResponse, error) { + return c.ContentClient.ListStatuses(ctx, req) +} + +type convertWriteClient struct { + contentapi.Content_WriteClient +} + +func (c convertClient) Write(ctx context.Context) (contentapi.TTRPCContent_WriteClient, error) { + wc, err := c.ContentClient.Write(ctx) + if wc == nil { + return nil, err + } + return convertWriteClient{wc}, err +} + +func (c convertClient) Abort(ctx context.Context, req *contentapi.AbortRequest) (*emptypb.Empty, error) { + return c.ContentClient.Abort(ctx, req) +} + func infoToGRPC(info *content.Info) *contentapi.Info { return &contentapi.Info{ Digest: info.Digest.String(), diff --git a/vendor/github.com/containerd/containerd/content/proxy/content_writer.go b/vendor/github.com/containerd/containerd/v2/core/content/proxy/content_writer.go similarity index 90% rename from vendor/github.com/containerd/containerd/content/proxy/content_writer.go rename to vendor/github.com/containerd/containerd/v2/core/content/proxy/content_writer.go index 185115b0a4..214a0a3351 100644 --- a/vendor/github.com/containerd/containerd/content/proxy/content_writer.go +++ b/vendor/github.com/containerd/containerd/v2/core/content/proxy/content_writer.go @@ -22,15 +22,16 @@ import ( "io" contentapi "github.com/containerd/containerd/api/services/content/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/protobuf" + "github.com/containerd/errdefs/pkg/errgrpc" digest "github.com/opencontainers/go-digest" + + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/protobuf" ) type remoteWriter struct { ref string - client contentapi.Content_WriteClient + client contentapi.TTRPCContent_WriteClient offset int64 digest digest.Digest } @@ -58,7 +59,7 @@ func (rw *remoteWriter) Status() (content.Status, error) { Action: contentapi.WriteAction_STAT, }) if err != nil { - return content.Status{}, fmt.Errorf("error getting writer status: %w", errdefs.FromGRPC(err)) + return content.Status{}, fmt.Errorf("error getting writer status: %w", errgrpc.ToNative(err)) } return content.Status{ @@ -83,7 +84,7 @@ func (rw *remoteWriter) Write(p []byte) (n int, err error) { Data: p, }) if err != nil { - return 0, fmt.Errorf("failed to send write: %w", errdefs.FromGRPC(err)) + return 0, fmt.Errorf("failed to send write: %w", errgrpc.ToNative(err)) } n = int(resp.Offset - offset) @@ -120,7 +121,7 @@ func (rw *remoteWriter) Commit(ctx context.Context, size int64, expected digest. Labels: base.Labels, }) if err != nil { - return fmt.Errorf("commit failed: %w", errdefs.FromGRPC(err)) + return fmt.Errorf("commit failed: %w", errgrpc.ToNative(err)) } if size != 0 && resp.Offset != size { diff --git a/vendor/github.com/containerd/containerd/diff/diff.go b/vendor/github.com/containerd/containerd/v2/core/diff/diff.go similarity index 94% rename from vendor/github.com/containerd/containerd/diff/diff.go rename to vendor/github.com/containerd/containerd/v2/core/diff/diff.go index 5af4190c23..4838a1c37e 100644 --- a/vendor/github.com/containerd/containerd/diff/diff.go +++ b/vendor/github.com/containerd/containerd/v2/core/diff/diff.go @@ -21,7 +21,7 @@ import ( "io" "time" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/typeurl/v2" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -127,15 +127,6 @@ func WithPayloads(payloads map[string]typeurl.Any) ApplyOpt { } } -// WithSourceDateEpoch specifies the timestamp used for whiteouts to provide control for reproducibility. -// See also https://reproducible-builds.org/docs/source-date-epoch/ . -func WithSourceDateEpoch(tm *time.Time) Opt { - return func(c *Config) error { - c.SourceDateEpoch = tm - return nil - } -} - // WithSyncFs sets sync flag to the config. func WithSyncFs(sync bool) ApplyOpt { return func(_ context.Context, _ ocispec.Descriptor, c *ApplyConfig) error { @@ -143,3 +134,15 @@ func WithSyncFs(sync bool) ApplyOpt { return nil } } + +// WithSourceDateEpoch specifies the timestamp used to provide control for reproducibility. +// See also https://reproducible-builds.org/docs/source-date-epoch/ . +// +// Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01), +// not to the source date epoch. +func WithSourceDateEpoch(tm *time.Time) Opt { + return func(c *Config) error { + c.SourceDateEpoch = tm + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/diff/proxy/differ.go b/vendor/github.com/containerd/containerd/v2/core/diff/proxy/differ.go similarity index 62% rename from vendor/github.com/containerd/containerd/diff/proxy/differ.go rename to vendor/github.com/containerd/containerd/v2/core/diff/proxy/differ.go index 1492dc6738..8a5a4abd1e 100644 --- a/vendor/github.com/containerd/containerd/diff/proxy/differ.go +++ b/vendor/github.com/containerd/containerd/v2/core/diff/proxy/differ.go @@ -20,17 +20,16 @@ import ( "context" diffapi "github.com/containerd/containerd/api/services/diff/v1" - "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/pkg/epoch" - "github.com/containerd/containerd/protobuf" - ptypes "github.com/containerd/containerd/protobuf/types" - "github.com/opencontainers/go-digest" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/typeurl/v2" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "google.golang.org/protobuf/types/known/timestamppb" + + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/epoch" + "github.com/containerd/containerd/v2/pkg/oci" + ptypes "github.com/containerd/containerd/v2/pkg/protobuf/types" ) // NewDiffApplier returns a new comparer and applier which communicates @@ -55,20 +54,20 @@ func (r *diffRemote) Apply(ctx context.Context, desc ocispec.Descriptor, mounts payloads := make(map[string]*ptypes.Any) for k, v := range config.ProcessorPayloads { - payloads[k] = protobuf.FromAny(v) + payloads[k] = typeurl.MarshalProto(v) } req := &diffapi.ApplyRequest{ - Diff: fromDescriptor(desc), - Mounts: fromMounts(mounts), + Diff: oci.DescriptorToProto(desc), + Mounts: mount.ToProto(mounts), Payloads: payloads, SyncFs: config.SyncFs, } resp, err := r.client.Apply(ctx, req) if err != nil { - return ocispec.Descriptor{}, errdefs.FromGRPC(err) + return ocispec.Descriptor{}, errgrpc.ToNative(err) } - return toDescriptor(resp.Applied), nil + return oci.DescriptorFromProto(resp.Applied), nil } func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...diff.Opt) (ocispec.Descriptor, error) { @@ -86,8 +85,8 @@ func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...di sourceDateEpoch = timestamppb.New(*config.SourceDateEpoch) } req := &diffapi.DiffRequest{ - Left: fromMounts(a), - Right: fromMounts(b), + Left: mount.ToProto(a), + Right: mount.ToProto(b), MediaType: config.MediaType, Ref: config.Reference, Labels: config.Labels, @@ -95,38 +94,7 @@ func (r *diffRemote) Compare(ctx context.Context, a, b []mount.Mount, opts ...di } resp, err := r.client.Diff(ctx, req) if err != nil { - return ocispec.Descriptor{}, errdefs.FromGRPC(err) + return ocispec.Descriptor{}, errgrpc.ToNative(err) } - return toDescriptor(resp.Diff), nil -} - -func toDescriptor(d *types.Descriptor) ocispec.Descriptor { - return ocispec.Descriptor{ - MediaType: d.MediaType, - Digest: digest.Digest(d.Digest), - Size: d.Size, - Annotations: d.Annotations, - } -} - -func fromDescriptor(d ocispec.Descriptor) *types.Descriptor { - return &types.Descriptor{ - MediaType: d.MediaType, - Digest: d.Digest.String(), - Size: d.Size, - Annotations: d.Annotations, - } -} - -func fromMounts(mounts []mount.Mount) []*types.Mount { - apiMounts := make([]*types.Mount, len(mounts)) - for i, m := range mounts { - apiMounts[i] = &types.Mount{ - Type: m.Type, - Source: m.Source, - Target: m.Target, - Options: m.Options, - } - } - return apiMounts + return oci.DescriptorFromProto(resp.Diff), nil } diff --git a/vendor/github.com/containerd/containerd/diff/stream.go b/vendor/github.com/containerd/containerd/v2/core/diff/stream.go similarity index 97% rename from vendor/github.com/containerd/containerd/diff/stream.go rename to vendor/github.com/containerd/containerd/v2/core/diff/stream.go index b80e6d1a5c..f44f8fa9ca 100644 --- a/vendor/github.com/containerd/containerd/diff/stream.go +++ b/vendor/github.com/containerd/containerd/v2/core/diff/stream.go @@ -22,8 +22,8 @@ import ( "io" "os" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/containerd/typeurl/v2" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/containerd/containerd/diff/stream_unix.go b/vendor/github.com/containerd/containerd/v2/core/diff/stream_unix.go similarity index 96% rename from vendor/github.com/containerd/containerd/diff/stream_unix.go rename to vendor/github.com/containerd/containerd/v2/core/diff/stream_unix.go index 893456b9d4..28ef3b45b9 100644 --- a/vendor/github.com/containerd/containerd/diff/stream_unix.go +++ b/vendor/github.com/containerd/containerd/v2/core/diff/stream_unix.go @@ -28,8 +28,7 @@ import ( "os/exec" "sync" - "github.com/containerd/containerd/protobuf" - "github.com/containerd/containerd/protobuf/proto" + "github.com/containerd/containerd/v2/pkg/protobuf/proto" "github.com/containerd/typeurl/v2" ) @@ -41,7 +40,7 @@ func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProce var payloadC io.Closer if payload != nil { - pb := protobuf.FromAny(payload) + pb := typeurl.MarshalProto(payload) data, err := proto.Marshal(pb) if err != nil { return nil, err diff --git a/vendor/github.com/containerd/containerd/diff/stream_windows.go b/vendor/github.com/containerd/containerd/v2/core/diff/stream_windows.go similarity index 93% rename from vendor/github.com/containerd/containerd/diff/stream_windows.go rename to vendor/github.com/containerd/containerd/v2/core/diff/stream_windows.go index b5ce526644..4f068cfc15 100644 --- a/vendor/github.com/containerd/containerd/diff/stream_windows.go +++ b/vendor/github.com/containerd/containerd/v2/core/diff/stream_windows.go @@ -27,11 +27,11 @@ import ( "path/filepath" "sync" - winio "github.com/Microsoft/go-winio" - "github.com/containerd/containerd/protobuf" - "github.com/containerd/containerd/protobuf/proto" + "github.com/Microsoft/go-winio" + + "github.com/containerd/containerd/v2/pkg/protobuf/proto" + "github.com/containerd/log" "github.com/containerd/typeurl/v2" - "github.com/sirupsen/logrus" ) const processorPipe = "STREAM_PROCESSOR_PIPE" @@ -43,7 +43,7 @@ func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProce cmd.Env = append(cmd.Env, env...) if payload != nil { - pb := protobuf.FromAny(payload) + pb := typeurl.MarshalProto(payload) data, err := proto.Marshal(pb) if err != nil { return nil, err @@ -61,7 +61,7 @@ func NewBinaryProcessor(ctx context.Context, imt, rmt string, stream StreamProce defer l.Close() conn, err := l.Accept() if err != nil { - logrus.WithError(err).Error("accept npipe connection") + log.G(ctx).WithError(err).Error("accept npipe connection") return } io.Copy(conn, bytes.NewReader(data)) diff --git a/vendor/github.com/containerd/containerd/events/events.go b/vendor/github.com/containerd/containerd/v2/core/events/events.go similarity index 100% rename from vendor/github.com/containerd/containerd/events/events.go rename to vendor/github.com/containerd/containerd/v2/core/events/events.go diff --git a/vendor/github.com/containerd/containerd/v2/core/events/proxy/remote_events.go b/vendor/github.com/containerd/containerd/v2/core/events/proxy/remote_events.go new file mode 100644 index 0000000000..db989230d5 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/events/proxy/remote_events.go @@ -0,0 +1,224 @@ +/* + 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 proxy + +import ( + "context" + "fmt" + + api "github.com/containerd/containerd/api/services/events/v1" + "github.com/containerd/containerd/api/types" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/ttrpc" + "github.com/containerd/typeurl/v2" + "google.golang.org/grpc" + + "github.com/containerd/containerd/v2/core/events" + "github.com/containerd/containerd/v2/pkg/protobuf" +) + +type EventService interface { + events.Publisher + events.Forwarder + events.Subscriber +} + +func NewRemoteEvents(client any) EventService { + switch c := client.(type) { + case api.EventsClient: + return &grpcEventsProxy{ + client: c, + } + case api.TTRPCEventsClient: + return &ttrpcEventsProxy{ + client: c, + } + case grpc.ClientConnInterface: + return &grpcEventsProxy{ + client: api.NewEventsClient(c), + } + case *ttrpc.Client: + return &ttrpcEventsProxy{ + client: api.NewTTRPCEventsClient(c), + } + default: + panic(fmt.Errorf("unsupported events client %T: %w", client, errdefs.ErrNotImplemented)) + } +} + +type grpcEventsProxy struct { + client api.EventsClient +} + +func (p *grpcEventsProxy) Publish(ctx context.Context, topic string, event events.Event) error { + evt, err := typeurl.MarshalAny(event) + if err != nil { + return err + } + req := &api.PublishRequest{ + Topic: topic, + Event: typeurl.MarshalProto(evt), + } + if _, err := p.client.Publish(ctx, req); err != nil { + return errgrpc.ToNative(err) + } + return nil +} + +func (p *grpcEventsProxy) Forward(ctx context.Context, envelope *events.Envelope) error { + req := &api.ForwardRequest{ + Envelope: &types.Envelope{ + Timestamp: protobuf.ToTimestamp(envelope.Timestamp), + Namespace: envelope.Namespace, + Topic: envelope.Topic, + Event: typeurl.MarshalProto(envelope.Event), + }, + } + if _, err := p.client.Forward(ctx, req); err != nil { + return errgrpc.ToNative(err) + } + return nil +} + +func (p *grpcEventsProxy) Subscribe(ctx context.Context, filters ...string) (ch <-chan *events.Envelope, errs <-chan error) { + var ( + evq = make(chan *events.Envelope) + errq = make(chan error, 1) + ) + + errs = errq + ch = evq + + session, err := p.client.Subscribe(ctx, &api.SubscribeRequest{ + Filters: filters, + }) + if err != nil { + errq <- err + close(errq) + return + } + + go func() { + defer close(errq) + + for { + ev, err := session.Recv() + if err != nil { + errq <- err + return + } + + select { + case evq <- &events.Envelope{ + Timestamp: protobuf.FromTimestamp(ev.Timestamp), + Namespace: ev.Namespace, + Topic: ev.Topic, + Event: ev.Event, + }: + case <-ctx.Done(): + if cerr := ctx.Err(); cerr != context.Canceled { + errq <- cerr + } + return + } + } + }() + + return ch, errs +} + +type ttrpcEventsProxy struct { + client api.TTRPCEventsClient +} + +func (p *ttrpcEventsProxy) Publish(ctx context.Context, topic string, event events.Event) error { + evt, err := typeurl.MarshalAny(event) + if err != nil { + return err + } + req := &api.PublishRequest{ + Topic: topic, + Event: typeurl.MarshalProto(evt), + } + if _, err := p.client.Publish(ctx, req); err != nil { + return errgrpc.ToNative(err) + } + return nil +} + +func (p *ttrpcEventsProxy) Forward(ctx context.Context, envelope *events.Envelope) error { + req := &api.ForwardRequest{ + Envelope: &types.Envelope{ + Timestamp: protobuf.ToTimestamp(envelope.Timestamp), + Namespace: envelope.Namespace, + Topic: envelope.Topic, + Event: typeurl.MarshalProto(envelope.Event), + }, + } + if _, err := p.client.Forward(ctx, req); err != nil { + return errgrpc.ToNative(err) + } + return nil +} + +func (p *ttrpcEventsProxy) Subscribe(ctx context.Context, filters ...string) (ch <-chan *events.Envelope, errs <-chan error) { + var ( + evq = make(chan *events.Envelope) + errq = make(chan error, 1) + ) + + errs = errq + ch = evq + + session, err := p.client.Subscribe(ctx, &api.SubscribeRequest{ + Filters: filters, + }) + if err != nil { + errq <- err + close(errq) + return + } + + go func() { + defer close(errq) + + for { + ev, err := session.Recv() + if err != nil { + errq <- err + return + } + + select { + case evq <- &events.Envelope{ + Timestamp: protobuf.FromTimestamp(ev.Timestamp), + Namespace: ev.Namespace, + Topic: ev.Topic, + Event: ev.Event, + }: + case <-ctx.Done(): + if cerr := ctx.Err(); cerr != context.Canceled { + errq <- cerr + } + return + } + } + }() + + return ch, errs +} diff --git a/vendor/github.com/containerd/containerd/images/annotations.go b/vendor/github.com/containerd/containerd/v2/core/images/annotations.go similarity index 100% rename from vendor/github.com/containerd/containerd/images/annotations.go rename to vendor/github.com/containerd/containerd/v2/core/images/annotations.go diff --git a/vendor/github.com/containerd/containerd/images/archive/exporter.go b/vendor/github.com/containerd/containerd/v2/core/images/archive/exporter.go similarity index 92% rename from vendor/github.com/containerd/containerd/images/archive/exporter.go rename to vendor/github.com/containerd/containerd/v2/core/images/archive/exporter.go index 3d53aca8e6..3d98daea1d 100644 --- a/vendor/github.com/containerd/containerd/images/archive/exporter.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/archive/exporter.go @@ -26,16 +26,15 @@ import ( "sort" "strings" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" ) type exportOptions struct { @@ -213,7 +212,7 @@ func copySourceLabels(ctx context.Context, infoProvider content.InfoProvider, de } // Export implements Exporter. -func Export(ctx context.Context, store content.Provider, writer io.Writer, opts ...ExportOpt) error { +func Export(ctx context.Context, store content.InfoReaderProvider, writer io.Writer, opts ...ExportOpt) error { var eo exportOptions for _, opt := range opts { if err := opt(ctx, &eo); err != nil { @@ -226,17 +225,13 @@ func Export(ctx context.Context, store content.Provider, writer io.Writer, opts } manifests := make([]ocispec.Descriptor, 0, len(eo.manifests)) - if infoProvider, ok := store.(content.InfoProvider); ok { - for _, desc := range eo.manifests { - d, err := copySourceLabels(ctx, infoProvider, desc) - if err != nil { - log.G(ctx).WithError(err).WithField("desc", desc).Warn("failed to copy distribution.source labels") - continue - } - manifests = append(manifests, d) + for _, desc := range eo.manifests { + d, err := copySourceLabels(ctx, store, desc) + if err != nil { + log.G(ctx).WithError(err).WithField("desc", desc).Warn("failed to copy distribution.source labels") + continue } - } else { - manifests = append(manifests, eo.manifests...) + manifests = append(manifests, d) } algorithms := map[string]struct{}{} @@ -399,10 +394,9 @@ func blobRecord(cs content.Provider, desc ocispec.Descriptor, opts *blobRecordOp if opts != nil && opts.blobFilter != nil && !opts.blobFilter(desc) { return tarRecord{} } - path := path.Join("blobs", desc.Digest.Algorithm().String(), desc.Digest.Encoded()) return tarRecord{ Header: &tar.Header{ - Name: path, + Name: path.Join(ocispec.ImageBlobsDir, desc.Digest.Algorithm().String(), desc.Digest.Encoded()), Mode: 0444, Size: desc.Size, Typeflag: tar.TypeReg, @@ -483,7 +477,7 @@ func ociIndexRecord(manifests []ocispec.Descriptor) tarRecord { return tarRecord{ Header: &tar.Header{ - Name: "index.json", + Name: ocispec.ImageIndexFile, Mode: 0644, Size: int64(len(b)), Typeflag: tar.TypeReg, @@ -518,18 +512,14 @@ func manifestsRecord(ctx context.Context, store content.Provider, manifests map[ if err := json.Unmarshal(p, &manifest); err != nil { return tarRecord{}, err } - if err := manifest.Config.Digest.Validate(); err != nil { - return tarRecord{}, fmt.Errorf("invalid manifest %q: %w", m.manifest.Digest, err) - } dgst := manifest.Config.Digest if err := dgst.Validate(); err != nil { return tarRecord{}, err } - mfsts[i].Config = path.Join("blobs", dgst.Algorithm().String(), dgst.Encoded()) + mfsts[i].Config = path.Join(ocispec.ImageBlobsDir, dgst.Algorithm().String(), dgst.Encoded()) for _, l := range manifest.Layers { - path := path.Join("blobs", l.Digest.Algorithm().String(), l.Digest.Encoded()) - mfsts[i].Layers = append(mfsts[i].Layers, path) + mfsts[i].Layers = append(mfsts[i].Layers, path.Join(ocispec.ImageBlobsDir, l.Digest.Algorithm().String(), l.Digest.Encoded())) } for _, name := range m.names { diff --git a/vendor/github.com/containerd/containerd/images/archive/importer.go b/vendor/github.com/containerd/containerd/v2/core/images/archive/importer.go similarity index 96% rename from vendor/github.com/containerd/containerd/images/archive/importer.go rename to vendor/github.com/containerd/containerd/v2/core/images/archive/importer.go index 99712da740..64a1587f77 100644 --- a/vendor/github.com/containerd/containerd/images/archive/importer.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/archive/importer.go @@ -27,11 +27,11 @@ import ( "io" "path" - "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/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" digest "github.com/opencontainers/go-digest" @@ -133,7 +133,7 @@ func ImportIndex(ctx context.Context, store content.Store, reader io.Reader, opt return ocispec.Descriptor{}, fmt.Errorf("unsupported OCI version %s", ociLayout.Version) } - idx, ok := blobs["index.json"] + idx, ok := blobs[ocispec.ImageIndexFile] if !ok { return ocispec.Descriptor{}, fmt.Errorf("missing index.json in OCI layout %s", ocispec.ImageLayoutVersion) } @@ -256,8 +256,8 @@ func onUntarBlob(ctx context.Context, r io.Reader, store content.Ingester, size func resolveLayers(ctx context.Context, store content.Store, layerFiles []string, blobs map[string]ocispec.Descriptor, compress bool) ([]ocispec.Descriptor, error) { layers := make([]ocispec.Descriptor, len(layerFiles)) + filters := make([]string, len(layerFiles)) descs := map[digest.Digest]*ocispec.Descriptor{} - filters := []string{} for i, f := range layerFiles { desc, ok := blobs[f] if !ok { @@ -265,7 +265,7 @@ func resolveLayers(ctx context.Context, store content.Store, layerFiles []string } layers[i] = desc descs[desc.Digest] = &layers[i] - filters = append(filters, fmt.Sprintf("labels.\"%s\"==%s", labels.LabelUncompressed, desc.Digest.String())) + filters[i] = fmt.Sprintf("labels.\"%s\"==%s", labels.LabelUncompressed, desc.Digest.String()) } err := store.Walk(ctx, func(info content.Info) error { diff --git a/vendor/github.com/containerd/containerd/images/archive/reference.go b/vendor/github.com/containerd/containerd/v2/core/images/archive/reference.go similarity index 96% rename from vendor/github.com/containerd/containerd/images/archive/reference.go rename to vendor/github.com/containerd/containerd/v2/core/images/archive/reference.go index 8dc2099058..5e12eb98f4 100644 --- a/vendor/github.com/containerd/containerd/images/archive/reference.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/archive/reference.go @@ -20,7 +20,7 @@ import ( "fmt" "strings" - "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/v2/pkg/reference" distref "github.com/distribution/reference" "github.com/opencontainers/go-digest" ) @@ -72,7 +72,6 @@ func isImagePrefix(s, prefix string) bool { } func normalizeReference(ref string) (string, error) { - // TODO: Replace this function to not depend on reference package normalized, err := distref.ParseDockerRef(ref) if err != nil { return "", fmt.Errorf("normalize image ref %q: %w", ref, err) diff --git a/vendor/github.com/containerd/containerd/images/converter/converter.go b/vendor/github.com/containerd/containerd/v2/core/images/converter/converter.go similarity index 95% rename from vendor/github.com/containerd/containerd/images/converter/converter.go rename to vendor/github.com/containerd/containerd/v2/core/images/converter/converter.go index 4cacf90ba2..20308cb55a 100644 --- a/vendor/github.com/containerd/containerd/images/converter/converter.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/converter/converter.go @@ -20,9 +20,9 @@ package converter import ( "context" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" "github.com/containerd/platforms" ) diff --git a/vendor/github.com/containerd/containerd/images/converter/default.go b/vendor/github.com/containerd/containerd/v2/core/images/converter/default.go similarity index 98% rename from vendor/github.com/containerd/containerd/images/converter/default.go rename to vendor/github.com/containerd/containerd/v2/core/images/converter/default.go index 746bdd1ab1..98f7965367 100644 --- a/vendor/github.com/containerd/containerd/images/converter/default.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/converter/default.go @@ -24,12 +24,12 @@ import ( "strings" "sync" - "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" "github.com/containerd/platforms" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" "golang.org/x/sync/errgroup" ) @@ -123,7 +123,7 @@ func (c *defaultConverter) convert(ctx context.Context, cs content.Store, desc o newDesc.Annotations = nil } } - logrus.WithField("old", desc).WithField("new", newDesc).Debugf("converted") + log.G(ctx).WithField("old", desc).WithField("new", newDesc).Debugf("converted") return newDesc, nil } diff --git a/vendor/github.com/containerd/containerd/images/diffid.go b/vendor/github.com/containerd/containerd/v2/core/images/diffid.go similarity index 87% rename from vendor/github.com/containerd/containerd/images/diffid.go rename to vendor/github.com/containerd/containerd/v2/core/images/diffid.go index 85577eedee..140d2c07c6 100644 --- a/vendor/github.com/containerd/containerd/images/diffid.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/diffid.go @@ -20,12 +20,13 @@ import ( "context" "io" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/labels" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" + + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/log" ) // GetDiffID gets the diff ID of the layer blob descriptor. @@ -75,7 +76,7 @@ func GetDiffID(ctx context.Context, cs content.Store, desc ocispec.Descriptor) ( } info.Labels[labels.LabelUncompressed] = digest.String() if _, err := cs.Update(ctx, info, "labels"); err != nil { - logrus.WithError(err).Warnf("failed to set %s label for %s", labels.LabelUncompressed, desc.Digest) + log.G(ctx).WithError(err).Warnf("failed to set %s label for %s", labels.LabelUncompressed, desc.Digest) } return digest, nil } diff --git a/vendor/github.com/containerd/containerd/images/handlers.go b/vendor/github.com/containerd/containerd/v2/core/images/handlers.go similarity index 97% rename from vendor/github.com/containerd/containerd/images/handlers.go rename to vendor/github.com/containerd/containerd/v2/core/images/handlers.go index a685092e2c..0487fdebda 100644 --- a/vendor/github.com/containerd/containerd/images/handlers.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/handlers.go @@ -22,13 +22,12 @@ import ( "fmt" "sort" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/errdefs" "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/errgroup" "golang.org/x/sync/semaphore" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" ) var ( @@ -295,8 +294,8 @@ func LimitManifests(f HandlerFunc, m platforms.MatchComparer, n int) HandlerFunc return children, err } - switch desc.MediaType { - case ocispec.MediaTypeImageIndex, MediaTypeDockerSchema2ManifestList: + // only limit manifests from an index + if IsIndexType(desc.MediaType) { sort.SliceStable(children, func(i, j int) bool { if children[i].Platform == nil { return false @@ -315,8 +314,6 @@ func LimitManifests(f HandlerFunc, m platforms.MatchComparer, n int) HandlerFunc children = children[:n] } } - default: - // only limit manifests from an index } return children, nil } diff --git a/vendor/github.com/containerd/containerd/images/image.go b/vendor/github.com/containerd/containerd/v2/core/images/image.go similarity index 83% rename from vendor/github.com/containerd/containerd/images/image.go rename to vendor/github.com/containerd/containerd/v2/core/images/image.go index b934e34961..6bc106aac5 100644 --- a/vendor/github.com/containerd/containerd/images/image.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/image.go @@ -23,13 +23,12 @@ import ( "sort" "time" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" ) // Image provides the model for how containerd views container images. @@ -59,6 +58,7 @@ type Image struct { // DeleteOptions provide options on image delete type DeleteOptions struct { Synchronous bool + Target *ocispec.Descriptor } // DeleteOpt allows configuring a delete operation @@ -73,6 +73,16 @@ func SynchronousDelete() DeleteOpt { } } +// DeleteTarget is used to specify the target value an image is expected +// to have when deleting. If the image has a different target, then +// NotFound is returned. +func DeleteTarget(target *ocispec.Descriptor) DeleteOpt { + return func(ctx context.Context, o *DeleteOptions) error { + o.Target = target + return nil + } +} + // Store and interact with images type Store interface { Get(ctx context.Context, name string) (Image, error) @@ -148,8 +158,7 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc ) if err := Walk(ctx, HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { - switch desc.MediaType { - case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: + if IsManifestType(desc.MediaType) { p, err := content.ReadBlob(ctx, provider, desc) if err != nil { return nil, err @@ -170,17 +179,11 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc } if desc.Platform == nil { - p, err := content.ReadBlob(ctx, provider, manifest.Config) + imagePlatform, err := ConfigPlatform(ctx, provider, manifest.Config) if err != nil { return nil, err } - - var image ocispec.Image - if err := json.Unmarshal(p, &image); err != nil { - return nil, err - } - - if !platform.Match(platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture})) { + if !platform.Match(imagePlatform) { return nil, nil } @@ -193,7 +196,7 @@ func Manifest(ctx context.Context, provider content.Provider, image ocispec.Desc }) return nil, nil - case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: + } else if IsIndexType(desc.MediaType) { p, err := content.ReadBlob(ctx, provider, desc) if err != nil { return nil, err @@ -261,7 +264,7 @@ func Config(ctx context.Context, provider content.Provider, image ocispec.Descri if err != nil { return ocispec.Descriptor{}, err } - return manifest.Config, err + return manifest.Config, nil } // Platforms returns one or more platforms supported by the image. @@ -276,20 +279,12 @@ func Platforms(ctx context.Context, provider content.Provider, image ocispec.Des return nil, ErrSkipDesc } - switch desc.MediaType { - case MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig: - p, err := content.ReadBlob(ctx, provider, desc) + if IsConfigType(desc.MediaType) { + imagePlatform, err := ConfigPlatform(ctx, provider, desc) if err != nil { return nil, err } - - var image ocispec.Image - if err := json.Unmarshal(p, &image); err != nil { - return nil, err - } - - platformSpecs = append(platformSpecs, - platforms.Normalize(ocispec.Platform{OS: image.OS, Architecture: image.Architecture})) + platformSpecs = append(platformSpecs, imagePlatform) } return nil, nil }), ChildrenHandler(provider)), image) @@ -340,9 +335,7 @@ func Check(ctx context.Context, provider content.Provider, image ocispec.Descrip // Children returns the immediate children of content described by the descriptor. func Children(ctx context.Context, provider content.Provider, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { - var descs []ocispec.Descriptor - switch desc.MediaType { - case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: + if IsManifestType(desc.MediaType) { p, err := content.ReadBlob(ctx, provider, desc) if err != nil { return nil, err @@ -359,9 +352,8 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr return nil, err } - descs = append(descs, manifest.Config) - descs = append(descs, manifest.Layers...) - case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: + return append([]ocispec.Descriptor{manifest.Config}, manifest.Layers...), nil + } else if IsIndexType(desc.MediaType) { p, err := content.ReadBlob(ctx, provider, desc) if err != nil { return nil, err @@ -376,16 +368,12 @@ func Children(ctx context.Context, provider content.Provider, desc ocispec.Descr return nil, err } - descs = append(descs, index.Manifests...) - default: - if IsLayerType(desc.MediaType) || IsKnownConfig(desc.MediaType) { - // childless data types. - return nil, nil - } + return append([]ocispec.Descriptor{}, index.Manifests...), nil + } else if !IsLayerType(desc.MediaType) && !IsKnownConfig(desc.MediaType) { + // Layers and configs are childless data types and should not be logged. log.G(ctx).Debugf("encountered unknown type %v; children may not be fetched", desc.MediaType) } - - return descs, nil + return nil, nil } // unknownDocument represents a manifest, manifest list, or index that has not @@ -398,9 +386,10 @@ type unknownDocument struct { FSLayers json.RawMessage `json:"fsLayers,omitempty"` // schema 1 } -// validateMediaType returns an error if the byte slice is invalid JSON or if -// the media type identifies the blob as one format but it contains elements of -// another format. +// validateMediaType returns an error if the byte slice is invalid JSON, +// if the format of the blob is not supported, or if the media type +// identifies the blob as one format, but it identifies itself as, or +// contains elements of another format. func validateMediaType(b []byte, mt string) error { var doc unknownDocument if err := json.Unmarshal(b, &doc); err != nil { @@ -409,19 +398,10 @@ func validateMediaType(b []byte, mt string) error { if len(doc.FSLayers) != 0 { return fmt.Errorf("media-type: schema 1 not supported") } - switch mt { - case MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: - if len(doc.Manifests) != 0 || - doc.MediaType == MediaTypeDockerSchema2ManifestList || - doc.MediaType == ocispec.MediaTypeImageIndex { - return fmt.Errorf("media-type: expected manifest but found index (%s)", mt) - } - case MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: - if len(doc.Config) != 0 || len(doc.Layers) != 0 || - doc.MediaType == MediaTypeDockerSchema2Manifest || - doc.MediaType == ocispec.MediaTypeImageManifest { - return fmt.Errorf("media-type: expected index but found manifest (%s)", mt) - } + if IsManifestType(mt) && (len(doc.Manifests) != 0 || IsIndexType(doc.MediaType)) { + return fmt.Errorf("media-type: expected manifest but found index (%s)", mt) + } else if IsIndexType(mt) && (len(doc.Config) != 0 || len(doc.Layers) != 0 || IsManifestType(doc.MediaType)) { + return fmt.Errorf("media-type: expected index but found manifest (%s)", mt) } return nil } @@ -442,3 +422,19 @@ func RootFS(ctx context.Context, provider content.Provider, configDesc ocispec.D } return config.RootFS.DiffIDs, nil } + +// ConfigPlatform returns a normalized platform from an image manifest config. +func ConfigPlatform(ctx context.Context, provider content.Provider, configDesc ocispec.Descriptor) (ocispec.Platform, error) { + p, err := content.ReadBlob(ctx, provider, configDesc) + if err != nil { + return ocispec.Platform{}, err + } + + // Technically, this should be ocispec.Image, but we only need the + // ocispec.Platform that is embedded in the image struct. + var imagePlatform ocispec.Platform + if err := json.Unmarshal(p, &imagePlatform); err != nil { + return ocispec.Platform{}, err + } + return platforms.Normalize(imagePlatform), nil +} diff --git a/vendor/github.com/containerd/containerd/images/importexport.go b/vendor/github.com/containerd/containerd/v2/core/images/importexport.go similarity index 95% rename from vendor/github.com/containerd/containerd/images/importexport.go rename to vendor/github.com/containerd/containerd/v2/core/images/importexport.go index 843adcadc7..601d545ef0 100644 --- a/vendor/github.com/containerd/containerd/images/importexport.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/importexport.go @@ -20,7 +20,7 @@ import ( "context" "io" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/containerd/containerd/images/labels.go b/vendor/github.com/containerd/containerd/v2/core/images/labels.go similarity index 100% rename from vendor/github.com/containerd/containerd/images/labels.go rename to vendor/github.com/containerd/containerd/v2/core/images/labels.go diff --git a/vendor/github.com/containerd/containerd/images/mediatypes.go b/vendor/github.com/containerd/containerd/v2/core/images/mediatypes.go similarity index 96% rename from vendor/github.com/containerd/containerd/images/mediatypes.go rename to vendor/github.com/containerd/containerd/v2/core/images/mediatypes.go index d3b28d42dc..d2e845b16d 100644 --- a/vendor/github.com/containerd/containerd/images/mediatypes.go +++ b/vendor/github.com/containerd/containerd/v2/core/images/mediatypes.go @@ -22,7 +22,7 @@ import ( "sort" "strings" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -34,6 +34,7 @@ const ( MediaTypeDockerSchema2Layer = "application/vnd.docker.image.rootfs.diff.tar" MediaTypeDockerSchema2LayerForeign = "application/vnd.docker.image.rootfs.foreign.diff.tar" MediaTypeDockerSchema2LayerGzip = "application/vnd.docker.image.rootfs.diff.tar.gzip" + MediaTypeDockerSchema2LayerZstd = "application/vnd.docker.image.rootfs.diff.tar.zstd" MediaTypeDockerSchema2LayerForeignGzip = "application/vnd.docker.image.rootfs.foreign.diff.tar.gzip" MediaTypeDockerSchema2Config = "application/vnd.docker.container.image.v1+json" MediaTypeDockerSchema2Manifest = "application/vnd.docker.distribution.manifest.v2+json" @@ -81,6 +82,12 @@ func DiffCompression(ctx context.Context, mediaType string) (string, error) { return "", nil } return "gzip", nil + case MediaTypeDockerSchema2LayerZstd: + if len(ext) > 0 { + // Type is wrapped + return "", nil + } + return "zstd", nil case ocispec.MediaTypeImageLayer, ocispec.MediaTypeImageLayerNonDistributable: //nolint:staticcheck // Non-distributable layers are deprecated if len(ext) > 0 { switch ext[len(ext)-1] { @@ -132,7 +139,7 @@ func IsLayerType(mt string) bool { // Parse Docker media types, strip off any + suffixes first switch base, _ := parseMediaTypes(mt); base { case MediaTypeDockerSchema2Layer, MediaTypeDockerSchema2LayerGzip, - MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip: + MediaTypeDockerSchema2LayerForeign, MediaTypeDockerSchema2LayerForeignGzip, MediaTypeDockerSchema2LayerZstd: return true } return false diff --git a/vendor/github.com/containerd/containerd/v2/core/images/usage/calculator.go b/vendor/github.com/containerd/containerd/v2/core/images/usage/calculator.go new file mode 100644 index 0000000000..35477ba1a6 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/images/usage/calculator.go @@ -0,0 +1,167 @@ +/* + 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 usage + +import ( + "context" + "strings" + "sync/atomic" + + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/errdefs" + "github.com/containerd/platforms" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" + + "golang.org/x/sync/semaphore" +) + +type usageOptions struct { + platform platforms.MatchComparer + manifestLimit int + manifestOnly bool + snapshots func(name string) snapshots.Snapshotter +} + +type Opt func(*usageOptions) error + +// WithManifestLimit sets the limit to the number of manifests which will +// be walked for usage. Setting this value to 0 will require all manifests to +// be walked, returning ErrNotFound if manifests are missing. +// NOTE: By default all manifests which exist will be walked +// and any non-existent manifests and their subobjects will be ignored. +func WithManifestLimit(platform platforms.MatchComparer, i int) Opt { + // If 0 then don't filter any manifests + // By default limits to current platform + return func(o *usageOptions) error { + o.manifestLimit = i + o.platform = platform + return nil + } +} + +// WithSnapshotters will check for referenced snapshots from the image objects +// and include the snapshot size in the total usage. +func WithSnapshotters(f func(string) snapshots.Snapshotter) Opt { + return func(o *usageOptions) error { + o.snapshots = f + return nil + } +} + +// WithManifestUsage is used to get the usage for an image based on what is +// reported by the manifests rather than what exists in the content store. +// NOTE: This function is best used with the manifest limit set to get a +// consistent value, otherwise non-existent manifests will be excluded. +func WithManifestUsage() Opt { + return func(o *usageOptions) error { + o.manifestOnly = true + return nil + } +} + +func CalculateImageUsage(ctx context.Context, i images.Image, provider content.InfoReaderProvider, opts ...Opt) (int64, error) { + var config usageOptions + for _, opt := range opts { + if err := opt(&config); err != nil { + return 0, err + } + } + + var ( + handler = images.ChildrenHandler(provider) + size int64 + mustExist bool + ) + + if config.platform != nil { + handler = images.LimitManifests(handler, config.platform, config.manifestLimit) + mustExist = true + } + + var wh images.HandlerFunc = func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { + var usage int64 + children, err := handler(ctx, desc) + if err != nil { + if !errdefs.IsNotFound(err) || mustExist { + return nil, err + } + if !config.manifestOnly { + // Do not count size of non-existent objects + desc.Size = 0 + } + } else if config.snapshots != nil || !config.manifestOnly { + info, err := provider.Info(ctx, desc.Digest) + if err != nil { + if !errdefs.IsNotFound(err) { + return nil, err + } + if !config.manifestOnly { + // Do not count size of non-existent objects + desc.Size = 0 + } + } else { + if info.Size > desc.Size { + // Count actual usage, Size may be unset or -1 + desc.Size = info.Size + } + + if config.snapshots != nil { + for k, v := range info.Labels { + const prefix = "containerd.io/gc.ref.snapshot." + if !strings.HasPrefix(k, prefix) { + continue + } + + sn := config.snapshots(k[len(prefix):]) + if sn == nil { + continue + } + + u, err := sn.Usage(ctx, v) + if err != nil { + if !errdefs.IsNotFound(err) && !errdefs.IsInvalidArgument(err) { + return nil, err + } + } else { + usage += u.Size + } + } + } + } + } + + // Ignore unknown sizes. Generally unknown sizes should + // never be set in manifests, however, the usage + // calculation does not need to enforce this. + if desc.Size >= 0 { + usage += desc.Size + } + + atomic.AddInt64(&size, usage) + + return children, nil + } + + l := semaphore.NewWeighted(3) + if err := images.Dispatch(ctx, wh, l, i.Target); err != nil { + return 0, err + } + + return size, nil +} diff --git a/vendor/github.com/containerd/containerd/v2/core/introspection/introspection.go b/vendor/github.com/containerd/containerd/v2/core/introspection/introspection.go new file mode 100644 index 0000000000..6859a2b7c4 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/introspection/introspection.go @@ -0,0 +1,30 @@ +/* + 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 introspection + +import ( + context "context" + + api "github.com/containerd/containerd/api/services/introspection/v1" +) + +// Service defines the introspection service interface +type Service interface { + Plugins(context.Context, ...string) (*api.PluginsResponse, error) + Server(context.Context) (*api.ServerResponse, error) + PluginInfo(context.Context, string, string, any) (*api.PluginInfoResponse, error) +} diff --git a/vendor/github.com/containerd/containerd/v2/core/introspection/proxy/remote.go b/vendor/github.com/containerd/containerd/v2/core/introspection/proxy/remote.go new file mode 100644 index 0000000000..9e9b9b5d44 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/introspection/proxy/remote.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. +*/ + +package introspectionproxy + +import ( + "context" + "fmt" + + api "github.com/containerd/containerd/api/services/introspection/v1" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/log" + "github.com/containerd/ttrpc" + "github.com/containerd/typeurl/v2" + "google.golang.org/grpc" + "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/emptypb" + + "github.com/containerd/containerd/v2/core/introspection" +) + +var _ = (introspection.Service)(&introspectionRemote{}) + +// NewIntrospectionServiceFromClient creates a new introspection service from an API client +func NewIntrospectionProxy(client any) introspection.Service { + switch c := client.(type) { + case api.IntrospectionClient: + return &introspectionRemote{client: convertIntrospection{c}} + case api.TTRPCIntrospectionService: + return &introspectionRemote{client: c} + case grpc.ClientConnInterface: + return &introspectionRemote{client: convertIntrospection{api.NewIntrospectionClient(c)}} + case *ttrpc.Client: + return &introspectionRemote{client: api.NewTTRPCIntrospectionClient(c)} + default: + panic(fmt.Errorf("unsupported introspection client %T: %w", client, errdefs.ErrNotImplemented)) + } +} + +type introspectionRemote struct { + client api.TTRPCIntrospectionService +} + +func (i *introspectionRemote) Plugins(ctx context.Context, filters ...string) (*api.PluginsResponse, error) { + log.G(ctx).WithField("filters", filters).Debug("remote introspection plugin filters") + resp, err := i.client.Plugins(ctx, &api.PluginsRequest{ + Filters: filters, + }) + + if err != nil { + return nil, errgrpc.ToNative(err) + } + + return resp, nil +} + +func (i *introspectionRemote) Server(ctx context.Context) (*api.ServerResponse, error) { + resp, err := i.client.Server(ctx, &emptypb.Empty{}) + + if err != nil { + return nil, errgrpc.ToNative(err) + } + + return resp, nil +} + +func (i *introspectionRemote) PluginInfo(ctx context.Context, pluginType, id string, options any) (resp *api.PluginInfoResponse, err error) { + var optionsPB *anypb.Any + if options != nil { + optionsPB, err = typeurl.MarshalAnyToProto(options) + if err != nil { + return nil, fmt.Errorf("failed to marshal runtime requst: %w", err) + } + } + resp, err = i.client.PluginInfo(ctx, &api.PluginInfoRequest{ + Type: pluginType, + ID: id, + Options: optionsPB, + }) + + return resp, errgrpc.ToNative(err) +} + +type convertIntrospection struct { + client api.IntrospectionClient +} + +func (c convertIntrospection) Plugins(ctx context.Context, req *api.PluginsRequest) (*api.PluginsResponse, error) { + return c.client.Plugins(ctx, req) +} +func (c convertIntrospection) Server(ctx context.Context, in *emptypb.Empty) (*api.ServerResponse, error) { + return c.client.Server(ctx, in) +} +func (c convertIntrospection) PluginInfo(ctx context.Context, req *api.PluginInfoRequest) (*api.PluginInfoResponse, error) { + return c.client.PluginInfo(ctx, req) +} diff --git a/vendor/github.com/containerd/containerd/leases/context.go b/vendor/github.com/containerd/containerd/v2/core/leases/context.go similarity index 100% rename from vendor/github.com/containerd/containerd/leases/context.go rename to vendor/github.com/containerd/containerd/v2/core/leases/context.go diff --git a/vendor/github.com/containerd/containerd/leases/grpc.go b/vendor/github.com/containerd/containerd/v2/core/leases/grpc.go similarity index 100% rename from vendor/github.com/containerd/containerd/leases/grpc.go rename to vendor/github.com/containerd/containerd/v2/core/leases/grpc.go diff --git a/vendor/github.com/containerd/containerd/leases/id.go b/vendor/github.com/containerd/containerd/v2/core/leases/id.go similarity index 100% rename from vendor/github.com/containerd/containerd/leases/id.go rename to vendor/github.com/containerd/containerd/v2/core/leases/id.go diff --git a/vendor/github.com/containerd/containerd/leases/lease.go b/vendor/github.com/containerd/containerd/v2/core/leases/lease.go similarity index 87% rename from vendor/github.com/containerd/containerd/leases/lease.go rename to vendor/github.com/containerd/containerd/v2/core/leases/lease.go index fc0ca3491c..d842c4081a 100644 --- a/vendor/github.com/containerd/containerd/leases/lease.go +++ b/vendor/github.com/containerd/containerd/v2/core/leases/lease.go @@ -65,6 +65,19 @@ func SynchronousDelete(ctx context.Context, o *DeleteOptions) error { return nil } +// WithLabel sets a label on a lease, and merges it with existing labels. +// It overwrites the existing value of the given label (if present). +func WithLabel(label, value string) Opt { + return func(l *Lease) error { + if l.Labels == nil { + l.Labels = map[string]string{label: value} + return nil + } + l.Labels[label] = value + return nil + } +} + // WithLabels merges labels on a lease func WithLabels(labels map[string]string) Opt { return func(l *Lease) error { diff --git a/vendor/github.com/containerd/containerd/leases/proxy/manager.go b/vendor/github.com/containerd/containerd/v2/core/leases/proxy/manager.go similarity index 89% rename from vendor/github.com/containerd/containerd/leases/proxy/manager.go rename to vendor/github.com/containerd/containerd/v2/core/leases/proxy/manager.go index ae42d8eb10..1b5da798f4 100644 --- a/vendor/github.com/containerd/containerd/leases/proxy/manager.go +++ b/vendor/github.com/containerd/containerd/v2/core/leases/proxy/manager.go @@ -20,9 +20,10 @@ import ( "context" leasesapi "github.com/containerd/containerd/api/services/leases/v1" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/protobuf" + "github.com/containerd/errdefs/pkg/errgrpc" + + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/protobuf" ) type proxyManager struct { @@ -49,7 +50,7 @@ func (pm *proxyManager) Create(ctx context.Context, opts ...leases.Opt) (leases. Labels: l.Labels, }) if err != nil { - return leases.Lease{}, errdefs.FromGRPC(err) + return leases.Lease{}, errgrpc.ToNative(err) } return leases.Lease{ @@ -71,7 +72,7 @@ func (pm *proxyManager) Delete(ctx context.Context, l leases.Lease, opts ...leas ID: l.ID, Sync: do.Synchronous, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.Lease, error) { @@ -79,7 +80,7 @@ func (pm *proxyManager) List(ctx context.Context, filters ...string) ([]leases.L Filters: filters, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } l := make([]leases.Lease, len(resp.Leases)) for i := range resp.Leases { @@ -101,7 +102,7 @@ func (pm *proxyManager) AddResource(ctx context.Context, lease leases.Lease, r l Type: r.Type, }, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (pm *proxyManager) DeleteResource(ctx context.Context, lease leases.Lease, r leases.Resource) error { @@ -112,7 +113,7 @@ func (pm *proxyManager) DeleteResource(ctx context.Context, lease leases.Lease, Type: r.Type, }, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (pm *proxyManager) ListResources(ctx context.Context, lease leases.Lease) ([]leases.Resource, error) { @@ -120,7 +121,7 @@ func (pm *proxyManager) ListResources(ctx context.Context, lease leases.Lease) ( ID: lease.ID, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } rs := make([]leases.Resource, 0, len(resp.Resources)) diff --git a/vendor/github.com/containerd/containerd/metadata/adaptors.go b/vendor/github.com/containerd/containerd/v2/core/metadata/adaptors.go similarity index 91% rename from vendor/github.com/containerd/containerd/metadata/adaptors.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/adaptors.go index dbff7bacd9..16c63a0358 100644 --- a/vendor/github.com/containerd/containerd/metadata/adaptors.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/adaptors.go @@ -19,13 +19,13 @@ package metadata import ( "strings" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/sandbox" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/sandbox" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/filters" ) func adaptImage(o interface{}) filters.Adaptor { diff --git a/vendor/github.com/containerd/containerd/metadata/bolt.go b/vendor/github.com/containerd/containerd/v2/core/metadata/bolt.go similarity index 88% rename from vendor/github.com/containerd/containerd/metadata/bolt.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/bolt.go index 9edfab565b..50f26f2546 100644 --- a/vendor/github.com/containerd/containerd/metadata/bolt.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/bolt.go @@ -33,14 +33,15 @@ func WithTransactionContext(ctx context.Context, tx *bolt.Tx) context.Context { return context.WithValue(ctx, transactionKey{}, tx) } -type transactor interface { +// Transactor is the database interface for running transactions +type Transactor interface { View(fn func(*bolt.Tx) error) error Update(fn func(*bolt.Tx) error) error } // view gets a bolt db transaction either from the context // or starts a new one with the provided bolt database. -func view(ctx context.Context, db transactor, fn func(*bolt.Tx) error) error { +func view(ctx context.Context, db Transactor, fn func(*bolt.Tx) error) error { tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx) if !ok { return db.View(fn) @@ -50,7 +51,7 @@ func view(ctx context.Context, db transactor, fn func(*bolt.Tx) error) error { // update gets a writable bolt db transaction either from the context // or starts a new one with the provided bolt database. -func update(ctx context.Context, db transactor, fn func(*bolt.Tx) error) error { +func update(ctx context.Context, db Transactor, fn func(*bolt.Tx) error) error { tx, ok := ctx.Value(transactionKey{}).(*bolt.Tx) if !ok { return db.Update(fn) diff --git a/vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go b/vendor/github.com/containerd/containerd/v2/core/metadata/boltutil/helpers.go similarity index 96% rename from vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/boltutil/helpers.go index 8f8df33615..30df2e7a91 100644 --- a/vendor/github.com/containerd/containerd/metadata/boltutil/helpers.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/boltutil/helpers.go @@ -20,9 +20,8 @@ import ( "fmt" "time" - "github.com/containerd/containerd/protobuf" - "github.com/containerd/containerd/protobuf/proto" - "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/containerd/v2/pkg/protobuf/proto" + "github.com/containerd/containerd/v2/pkg/protobuf/types" "github.com/containerd/typeurl/v2" bolt "go.etcd.io/bbolt" ) @@ -164,7 +163,7 @@ func WriteExtensions(bkt *bolt.Bucket, extensions map[string]typeurl.Any) error } for name, ext := range extensions { - ext := protobuf.FromAny(ext) + ext := typeurl.MarshalProto(ext) p, err := proto.Marshal(ext) if err != nil { return err @@ -206,7 +205,7 @@ func ReadExtensions(bkt *bolt.Bucket) (map[string]typeurl.Any, error) { // WriteAny write a protobuf's Any type to the bucket func WriteAny(bkt *bolt.Bucket, name []byte, any typeurl.Any) error { - pbany := protobuf.FromAny(any) + pbany := typeurl.MarshalProto(any) if pbany == nil { return nil } diff --git a/vendor/github.com/containerd/containerd/metadata/buckets.go b/vendor/github.com/containerd/containerd/v2/core/metadata/buckets.go similarity index 56% rename from vendor/github.com/containerd/containerd/metadata/buckets.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/buckets.go index 8dcf10f475..bdfdafb4c9 100644 --- a/vendor/github.com/containerd/containerd/metadata/buckets.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/buckets.go @@ -28,98 +28,114 @@ // // /// -> // -// version: Currently, this is "v1". Additions can be made to v1 in a backwards -// compatible way. If the layout changes, a new version must be made, along -// with a migration. +// version +// Currently, this is "v1". Additions can be made to v1 in a backwards +// compatible way. If the layout changes, a new version must be made, +// along with a migration. // -// namespace: the namespace to which this object belongs. +// namespace +// The namespace to which this object belongs. // -// object: defines which object set is stored in the bucket. There are two -// special objects, "labels" and "indexes". The "labels" bucket stores the -// labels for the parent namespace. The "indexes" object is reserved for -// indexing objects, if we require in the future. +// object +// Defines which object set is stored in the bucket. There are two +// special objects, "labels" and "indexes". The "labels" bucket +// stores the labels for the parent namespace. The "indexes" object +// is reserved for indexing objects, if we require in the future. // -// key: object-specific key identifying the storage bucket for the objects -// contents. +// key +// Object-specific key identifying the storage bucket for the +// object's contents. // // Below is the current database schema. This should be updated each time // the structure is changed in addition to adding a migration and incrementing // the database version. -// Notes: // -// - `╘══*...*` refers to maps with arbitrary keys +// Notes +// • `╘══*...*` refers to maps with arbitrary keys +// • `version` is a key to a numeric value identifying the minor revisions +// of schema version +// • a namespace in a schema bucket cannot be named "version" // -// - `version` is a key to a numeric value identifying the minor revisions -// of schema version -// -// - a namespace in a schema bucket cannot be named "version" -// -// └──v1 - Schema version bucket -// ├──version : - Latest version, see migrations -// ╘══*namespace* -// ├──labels -// │  ╘══*key* : - Label value -// ├──image -// │  ╘══*image name* -// │   ├──createdat : - Created at -// │   ├──updatedat : - Updated at -// │   ├──target -// │   │  ├──digest : - Descriptor digest -// │   │  ├──mediatype : - Descriptor media type -// │   │  └──size : - Descriptor size -// │   └──labels -// │   ╘══*key* : - Label value -// ├──containers -// │  ╘══*container id* -// │   ├──createdat : - Created at -// │   ├──updatedat : - Updated at -// │   ├──spec : - Proto marshaled spec -// │   ├──image : - Image name -// │   ├──snapshotter : - Snapshotter name -// │   ├──snapshotKey : - Snapshot key -// │   ├──runtime -// │   │  ├──name : - Runtime name -// │   │  ├──extensions -// │   │  │  ╘══*name* : - Proto marshaled extension -// │   │  └──options : - Proto marshaled options -// │   └──labels -// │   ╘══*key* : - Label value -// ├──snapshots -// │  ╘══*snapshotter* -// │   ╘══*snapshot key* -// │    ├──name : - Snapshot name in backend -// │   ├──createdat : - Created at -// │   ├──updatedat : - Updated at -// │    ├──parent : - Parent snapshot name -// │   ├──children -// │   │  ╘══*snapshot key* : - Child snapshot reference -// │   └──labels -// │   ╘══*key* : - Label value -// ├──content -// │  ├──blob -// │  │ ╘══*blob digest* -// │  │ ├──createdat : - Created at -// │  │ ├──updatedat : - Updated at -// │  │   ├──size : - Blob size -// │  │ └──labels -// │  │ ╘══*key* : - Label value -// │  └──ingests -// │   ╘══*ingest reference* -// │    ├──ref : - Ingest reference in backend -// │   ├──expireat : - Time to expire ingest -// │   └──expected : - Expected commit digest -// └──leases -// ╘══*lease id* -// ├──createdat : - Created at -// ├──labels -// │ ╘══*key* : - Label value -// ├──snapshots -// │  ╘══*snapshotter* -// │   ╘══*snapshot key* : - Snapshot reference -// ├──content -// │  ╘══*blob digest* : - Content blob reference -// └──ingests -// ╘══*ingest reference* : - Content ingest reference +// Schema +// └──v1 - Schema version bucket +// ├──version : - Latest version, see migrations +// ╘══*namespace* +// ├──labels +// │ ╘══*key* : - Label value +// ├──image +// │ ╘══*image name* +// │ ├──createdat : - Created at +// │ ├──updatedat : - Updated at +// │ ├──target +// │ │ ├──digest : - Descriptor digest +// │ │ ├──mediatype : - Descriptor media type +// │ │ └──size : - Descriptor size +// │ └──labels +// │ ╘══*key* : - Label value +// ├──containers +// │ ╘══*container id* +// │ ├──createdat : - Created at +// │ ├──updatedat : - Updated at +// │ ├──spec : - Proto marshaled spec +// │ ├──image : - Image name +// │ ├──snapshotter : - Snapshotter name +// │ ├──snapshotKey : - Snapshot key +// │ ├──runtime +// │ │ ├──name : - Runtime name +// │ │ └──options : - Proto marshaled options +// │ ├──extensions +// │ │ ╘══*name* : - Proto marshaled extension +// │ └──labels +// │ ╘══*key* : - Label value +// ├──snapshots +// │ ╘══*snapshotter* +// │ ╘══*snapshot key* +// │ ├──name : - Snapshot name in backend +// │ ├──createdat : - Created at +// │ ├──updatedat : - Updated at +// │ ├──parent : - Parent snapshot name +// │ ├──children +// │ │ ╘══*snapshot key* : - Child snapshot reference +// │ └──labels +// │ ╘══*key* : - Label value +// ├──content +// │ ├──blob +// │ │ ╘══*blob digest* +// │ │ ├──createdat : - Created at +// │ │ ├──updatedat : - Updated at +// │ │ ├──size : - Blob size +// │ │ └──labels +// │ │ ╘══*key* : - Label value +// │ └──ingests +// │ ╘══*ingest reference* +// │ ├──ref : - Ingest reference in backend +// │ ├──expireat : - Time to expire ingest +// │ └──expected : - Expected commit digest +// ├──sandboxes +// │ ╘══*sandbox id* +// │ ├──createdat : - Created at +// │ ├──updatedat : - Updated at +// │ ├──spec : - Proto marshaled spec +// │ ├──sandboxer : - Sandboxer name +// │ ├──runtime +// │ │ ├──name : - Runtime name +// │ │ └──options : - Proto marshaled options +// │ ├──extensions +// │ │ ╘══*name* : - Proto marshaled extension +// │ └──labels +// │ ╘══*key* : - Label value +// └──leases +// ╘══*lease id* +// ├──createdat : - Created at +// ├──labels +// │ ╘══*key* : - Label value +// ├──snapshots +// │ ╘══*snapshotter* +// │ ╘══*snapshot key* : - Snapshot reference +// ├──content +// │ ╘══*blob digest* : - Content blob reference +// └─────ingests +// ╘══*ingest reference* : - Content ingest reference package metadata import ( @@ -159,6 +175,7 @@ var ( bucketKeyRef = []byte("ref") bucketKeyExpireAt = []byte("expireat") bucketKeySandboxID = []byte("sandboxid") + bucketKeySandboxer = []byte("sandboxer") deprecatedBucketKeyObjectIngest = []byte("ingest") // stores ingest links, deprecated in v1.2 ) @@ -284,6 +301,7 @@ func getIngestBucket(tx *bolt.Tx, namespace, ref string) *bolt.Bucket { func createSandboxBucket(tx *bolt.Tx, namespace string) (*bolt.Bucket, error) { return createBucketIfNotExists( tx, + bucketKeyVersion, []byte(namespace), bucketKeyObjectSandboxes, ) @@ -292,6 +310,7 @@ func createSandboxBucket(tx *bolt.Tx, namespace string) (*bolt.Bucket, error) { func getSandboxBucket(tx *bolt.Tx, namespace string) *bolt.Bucket { return getBucket( tx, + bucketKeyVersion, []byte(namespace), bucketKeyObjectSandboxes, ) diff --git a/vendor/github.com/containerd/containerd/metadata/containers.go b/vendor/github.com/containerd/containerd/v2/core/metadata/containers.go similarity index 87% rename from vendor/github.com/containerd/containerd/metadata/containers.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/containers.go index d97d9c6cd1..d49259679c 100644 --- a/vendor/github.com/containerd/containerd/metadata/containers.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/containers.go @@ -23,19 +23,24 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/identifiers" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/metadata/boltutil" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/protobuf/proto" - "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/metadata/boltutil" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/identifiers" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/pkg/protobuf/proto" + "github.com/containerd/containerd/v2/pkg/protobuf/types" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/errdefs" "github.com/containerd/typeurl/v2" bolt "go.etcd.io/bbolt" ) +const ( + spanContainerPrefix = "metadata.containers" +) + type containerStore struct { db *DB } @@ -116,6 +121,11 @@ func (s *containerStore) List(ctx context.Context, fs ...string) ([]containers.C } func (s *containerStore) Create(ctx context.Context, container containers.Container) (containers.Container, error) { + ctx, span := tracing.StartSpan(ctx, + tracing.Name(spanContainerPrefix, "Create"), + tracing.WithAttribute("container.id", container.ID), + ) + defer span.End() namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return containers.Container{}, err @@ -145,6 +155,9 @@ func (s *containerStore) Create(ctx context.Context, container containers.Contai return fmt.Errorf("failed to write container %q: %w", container.ID, err) } + span.SetAttributes( + tracing.Attribute("container.createdAt", container.CreatedAt.Format(time.RFC3339)), + ) return nil }); err != nil { return containers.Container{}, err @@ -154,6 +167,11 @@ func (s *containerStore) Create(ctx context.Context, container containers.Contai } func (s *containerStore) Update(ctx context.Context, container containers.Container, fieldpaths ...string) (containers.Container, error) { + ctx, span := tracing.StartSpan(ctx, + tracing.Name(spanContainerPrefix, "Update"), + tracing.WithAttribute("container.id", container.ID), + ) + defer span.End() namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return containers.Container{}, err @@ -245,6 +263,10 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai return fmt.Errorf("failed to write container %q: %w", container.ID, err) } + span.SetAttributes( + tracing.Attribute("container.createdAt", updated.CreatedAt.Format(time.RFC3339)), + tracing.Attribute("container.updatedAt", updated.UpdatedAt.Format(time.RFC3339)), + ) return nil }); err != nil { return containers.Container{}, err @@ -254,6 +276,12 @@ func (s *containerStore) Update(ctx context.Context, container containers.Contai } func (s *containerStore) Delete(ctx context.Context, id string) error { + ctx, span := tracing.StartSpan(ctx, + tracing.Name(spanContainerPrefix, "Delete"), + tracing.WithAttribute("container.id", id), + ) + defer span.End() + namespace, err := namespaces.NamespaceRequired(ctx) if err != nil { return err @@ -337,17 +365,17 @@ func readContainer(container *containers.Container, bkt *bolt.Bucket) error { container.Runtime.Name = string(n) } - any, err := boltutil.ReadAny(rbkt, bucketKeyOptions) + o, err := boltutil.ReadAny(rbkt, bucketKeyOptions) if err != nil { return err } - container.Runtime.Options = any + container.Runtime.Options = o case string(bucketKeySpec): - var any types.Any - if err := proto.Unmarshal(v, &any); err != nil { + var spec types.Any + if err := proto.Unmarshal(v, &spec); err != nil { return err } - container.Spec = &any + container.Spec = &spec case string(bucketKeySnapshotKey): container.SnapshotKey = string(v) case string(bucketKeySnapshotter): diff --git a/vendor/github.com/containerd/containerd/metadata/content.go b/vendor/github.com/containerd/containerd/v2/core/metadata/content.go similarity index 95% rename from vendor/github.com/containerd/containerd/metadata/content.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/content.go index 059c306ccd..bc42d6ca37 100644 --- a/vendor/github.com/containerd/containerd/metadata/content.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/content.go @@ -25,17 +25,17 @@ import ( "sync/atomic" "time" + "github.com/containerd/errdefs" "github.com/containerd/log" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" bolt "go.etcd.io/bbolt" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/metadata/boltutil" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/metadata/boltutil" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/namespaces" ) type contentStore struct { @@ -488,7 +488,7 @@ type namespacedWriter struct { ctx context.Context ref string namespace string - db transactor + db Transactor provider interface { content.Provider content.Ingester @@ -575,6 +575,18 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig var innerErr error + // We pre-sync the in-flight writes to the disk. This avoids the + // subsequent fp.Sync() call[1] from taking too long (10s+) while + // holding the metadata database lock as in the following `update` + // transaction. + // + // REF: + // [1]: https://github.com/containerd/containerd/blob/c4c3c6ea568ce0cfbcf754863abadeea37d77c8f/plugins/content/local/writer.go#L95 + if err := nw.Sync(); err != nil { + nw.Close() + return fmt.Errorf("failed to perform sync: %w", err) + } + if err := update(ctx, nw.db, func(tx *bolt.Tx) error { dgst, err := nw.commit(ctx, tx, size, expected, opts...) if err != nil { @@ -600,6 +612,13 @@ func (nw *namespacedWriter) Commit(ctx context.Context, size int64, expected dig return innerErr } +func (nw *namespacedWriter) Sync() error { + if syncer, ok := nw.w.(content.Syncer); ok { + return syncer.Sync() + } + return nil +} + func (nw *namespacedWriter) commit(ctx context.Context, tx *bolt.Tx, size int64, expected digest.Digest, opts ...content.Opt) (digest.Digest, error) { var base content.Info for _, opt := range opts { @@ -720,15 +739,8 @@ func isSharedContent(tx *bolt.Tx, dgst digest.Digest) bool { if lbkt == nil { continue } - // iterate through each label - lbc := lbkt.Cursor() - for k, v := lbc.First(); k != nil; k, v = lbc.Next() { - if string(k) == labels.LabelSharedNamespace { - if string(v) == "true" && getBlobBucket(tx, ns, dgst) != nil { - return true - } - break - } + if sharedNS := lbkt.Get([]byte(labels.LabelSharedNamespace)); sharedNS != nil && string(sharedNS) == "true" && getBlobBucket(tx, ns, dgst) != nil { + return true } } return false diff --git a/vendor/github.com/containerd/containerd/metadata/db.go b/vendor/github.com/containerd/containerd/v2/core/metadata/db.go similarity index 93% rename from vendor/github.com/containerd/containerd/metadata/db.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/db.go index 7be54f796c..6d3a7404d4 100644 --- a/vendor/github.com/containerd/containerd/metadata/db.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/db.go @@ -27,14 +27,15 @@ import ( "time" eventstypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/events" - "github.com/containerd/containerd/gc" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/pkg/cleanup" - "github.com/containerd/containerd/snapshots" "github.com/containerd/log" bolt "go.etcd.io/bbolt" + + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/events" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/internal/cleanup" + "github.com/containerd/containerd/v2/pkg/gc" + "github.com/containerd/containerd/v2/pkg/namespaces" ) const ( @@ -49,7 +50,7 @@ const ( // dbVersion represents updates to the schema // version which are additions and compatible with // prior version of the same schema. - dbVersion = 3 + dbVersion = 4 ) // DBOpt configures how we set up the DB @@ -80,7 +81,7 @@ type dbOptions struct { // while proxying data shared across namespaces to backend // datastores for content and snapshots. type DB struct { - db *bolt.DB + db Transactor ss map[string]*snapshotter cs *contentStore @@ -115,7 +116,7 @@ type DB struct { // NewDB creates a new metadata database using the provided // bolt database, content store, and snapshotters. -func NewDB(db *bolt.DB, cs content.Store, ss map[string]snapshots.Snapshotter, opts ...DBOpt) *DB { +func NewDB(db Transactor, cs content.Store, ss map[string]snapshots.Snapshotter, opts ...DBOpt) *DB { m := &DB{ db: db, ss: make(map[string]*snapshotter, len(ss)), @@ -270,6 +271,20 @@ func (m *DB) Update(fn func(*bolt.Tx) error) error { return err } +// Publisher returns an event publisher if one is configured +// and the current context is not inside a transaction. +func (m *DB) Publisher(ctx context.Context) events.Publisher { + _, ok := ctx.Value(transactionKey{}).(*bolt.Tx) + if ok { + // Do no publish events within a transaction + return nil + } + if m.dbopts.publisher != nil { + return m.dbopts.publisher + } + return nil +} + // RegisterMutationCallback registers a function to be called after a metadata // mutations has been performed. // @@ -325,6 +340,8 @@ func (m *DB) publishEvents(events []namespacedEvent) { ctx := namespaces.WithNamespace(ctx, ne.namespace) var topic string switch ne.event.(type) { + case *eventstypes.ImageDelete: + topic = "/images/delete" case *eventstypes.SnapshotRemove: topic = "/snapshot/remove" default: diff --git a/vendor/github.com/containerd/containerd/metadata/gc.go b/vendor/github.com/containerd/containerd/v2/core/metadata/gc.go similarity index 83% rename from vendor/github.com/containerd/containerd/metadata/gc.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/gc.go index 4a810ea3f2..1dd4f79f4f 100644 --- a/vendor/github.com/containerd/containerd/metadata/gc.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/gc.go @@ -25,7 +25,7 @@ import ( "time" eventstypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/gc" + "github.com/containerd/containerd/v2/pkg/gc" "github.com/containerd/log" bolt "go.etcd.io/bbolt" ) @@ -41,6 +41,8 @@ const ( ResourceContainer // ResourceTask specifies a task resource ResourceTask + // ResourceImage specifies an image + ResourceImage // ResourceLease specifies a lease ResourceLease // ResourceIngest specifies a content ingest @@ -54,6 +56,7 @@ const ( const ( resourceContentFlat = ResourceContent | 0x20 resourceSnapshotFlat = ResourceSnapshot | 0x20 + resourceImageFlat = ResourceImage | 0x20 ) var ( @@ -61,8 +64,22 @@ var ( labelGCRef = []byte("containerd.io/gc.ref.") labelGCSnapRef = []byte("containerd.io/gc.ref.snapshot.") labelGCContentRef = []byte("containerd.io/gc.ref.content") - labelGCExpire = []byte("containerd.io/gc.expire") - labelGCFlat = []byte("containerd.io/gc.flat") + labelGCImageRef = []byte("containerd.io/gc.ref.image") + + // labelGCExpire indicates that an object is collectible after the + // provided time. For image objects, this makes them available to + // garbage collect when expired, when not provided, image objects + // are root objects that never expire. For non-root objects such + // as content or snapshots, these objects will be treated like + // root objects before their expiration. + // Expected format is RFC 3339 + labelGCExpire = []byte("containerd.io/gc.expire") + + // labelGCFlat indicates that a lease is flat and only intends to + // lease the referenced objects, not their references. This can be + // used to avoid leasing an entire tree of objects when only the root + // object is needed. + labelGCFlat = []byte("containerd.io/gc.flat") ) // CollectionContext manages a resource collection during a single run of @@ -72,7 +89,7 @@ var ( // function and optimize other functions for running fast during garbage // collection write locks. type CollectionContext interface { - // Sends all known resources + // All sends all known resources All(func(gc.Node)) // Active sends all active resources @@ -137,6 +154,19 @@ func startGCContext(ctx context.Context, collectors map[gc.ResourceType]Collecto fn(gcnode(ResourceSnapshot, ns, fmt.Sprintf("%s/%s", snapshotter, v))) }, }, + { + key: labelGCImageRef, + fn: func(ns string, k, v []byte, fn func(gc.Node)) { + if ks := string(k); ks != string(labelGCImageRef) { + // Allow reference naming separated by . or /, ignore names + if ks[len(labelGCImageRef)] != '.' && ks[len(labelGCImageRef)] != '/' { + return + } + } + + fn(gcnode(ResourceImage, ns, string(v))) + }, + }, } if len(collectors) > 0 { contexts = map[gc.ResourceType]CollectionContext{} @@ -166,7 +196,7 @@ func startGCContext(ctx context.Context, collectors map[gc.ResourceType]Collecto } contexts[rt] = c } - // Sort labelHandlers to ensure key seeking is always forwardS + // Sort labelHandlers to ensure key seeking is always forward sort.Slice(labelHandlers, func(i, j int) bool { return bytes.Compare(labelHandlers[i].key, labelHandlers[j].key) < 0 }) @@ -260,6 +290,7 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod log.G(ctx).WithError(err).WithField("lease", string(k)).Infof("ignoring invalid expiration value %q", string(expV)) } else if expThreshold.After(exp) { // lease has expired, skip + log.G(ctx).WithField("lease", string(k)).Debug("expired lease") return nil } } @@ -323,6 +354,21 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod } } + itype := ResourceImage + if flat { + itype = resourceImageFlat + } + + ibkt = libkt.Bucket(bucketKeyObjectImages) + if ibkt != nil { + if err := ibkt.ForEach(func(k, v []byte) error { + fn(gcnode(itype, ns, string(k))) + return nil + }); err != nil { + return err + } + } + c.leased(ns, string(k), fn) return nil @@ -338,12 +384,10 @@ func (c *gcContext) scanRoots(ctx context.Context, tx *bolt.Tx, nc chan<- gc.Nod return nil } - target := ibkt.Bucket(k).Bucket(bucketKeyTarget) - if target != nil { - contentKey := string(target.Get(bucketKeyDigest)) - fn(gcnode(ResourceContent, ns, contentKey)) + if !isExpiredImage(ctx, k, ibkt.Bucket(k), expThreshold) { + fn(gcnode(ResourceImage, ns, string(k))) } - return c.sendLabelRefs(ns, ibkt.Bucket(k), fn) + return nil }); err != nil { return err } @@ -481,6 +525,31 @@ func (c *gcContext) references(ctx context.Context, tx *bolt.Tx, node gc.Node, f } return c.sendLabelRefs(node.Namespace, bkt, fn) + + case ResourceImage, resourceImageFlat: + bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectImages, []byte(node.Key)) + if bkt == nil { + // Node may be created from dead edge + return nil + } + target := bkt.Bucket(bucketKeyTarget) + if target != nil { + ctype := ResourceContent + if node.Type == resourceImageFlat { + // For flat leases, keep the target content only + ctype = resourceContentFlat + } + contentKey := string(target.Get(bucketKeyDigest)) + fn(gcnode(ctype, node.Namespace, contentKey)) + } + + // Do not send labeled references for flat image refs + if node.Type == resourceImageFlat { + return nil + } + + return c.sendLabelRefs(node.Namespace, bkt, fn) + case ResourceIngest: // Send expected value bkt := getBucket(tx, bucketKeyVersion, []byte(node.Namespace), bucketKeyObjectContent, bucketKeyObjectIngests, []byte(node.Key)) @@ -575,6 +644,19 @@ func (c *gcContext) scanAll(ctx context.Context, tx *bolt.Tx, fn func(ctx contex } } } + + ibkt := nbkt.Bucket(bucketKeyObjectImages) + if ibkt != nil { + if err := ibkt.ForEach(func(k, v []byte) error { + if v != nil { + return nil + } + node := gcnode(ResourceImage, ns, string(k)) + return fn(ctx, node) + }); err != nil { + return err + } + } } c.all(func(n gc.Node) { @@ -626,6 +708,13 @@ func (c *gcContext) remove(ctx context.Context, tx *bolt.Tx, node gc.Node) (inte }, ssbkt.DeleteBucket([]byte(key)) } } + case ResourceImage: + ibkt := nsbkt.Bucket(bucketKeyObjectImages) + if ibkt != nil { + return &eventstypes.ImageDelete{ + Name: node.Key, + }, ibkt.DeleteBucket([]byte(node.Key)) + } case ResourceLease: lbkt := nsbkt.Bucket(bucketKeyObjectLeases) if lbkt != nil { @@ -679,6 +768,22 @@ func isRootRef(bkt *bolt.Bucket) bool { return false } +func isExpiredImage(ctx context.Context, k []byte, bkt *bolt.Bucket, expTheshold time.Time) bool { + lbkt := bkt.Bucket(bucketKeyObjectLabels) + if lbkt != nil { + el := lbkt.Get(labelGCExpire) + if el != nil { + exp, err := time.Parse(time.RFC3339, string(el)) + if err != nil { + log.G(ctx).WithError(err).WithField("image", string(k)).Infof("ignoring invalid expiration value %q", string(el)) + return false + } + return expTheshold.After(exp) + } + } + return false +} + func gcnode(t gc.ResourceType, ns, key string) gc.Node { return gc.Node{ Type: t, diff --git a/vendor/github.com/containerd/containerd/metadata/images.go b/vendor/github.com/containerd/containerd/v2/core/metadata/images.go similarity index 82% rename from vendor/github.com/containerd/containerd/metadata/images.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/images.go index ff5b624cce..60291857d6 100644 --- a/vendor/github.com/containerd/containerd/metadata/images.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/images.go @@ -25,13 +25,14 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/metadata/boltutil" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/pkg/epoch" + eventstypes "github.com/containerd/containerd/api/events" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/metadata/boltutil" + "github.com/containerd/containerd/v2/pkg/epoch" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/errdefs" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" bolt "go.etcd.io/bbolt" @@ -136,6 +137,10 @@ func (s *imageStore) Create(ctx context.Context, image images.Image) (images.Ima return err } + if err := addImageLease(ctx, tx, image.Name, image.Labels); err != nil { + return err + } + ibkt, err := bkt.CreateBucket([]byte(image.Name)) if err != nil { if err != bolt.ErrBucketExists { @@ -160,6 +165,15 @@ func (s *imageStore) Create(ctx context.Context, image images.Image) (images.Ima return images.Image{}, err } + if publisher := s.db.Publisher(ctx); publisher != nil { + if err := publisher.Publish(ctx, "/images/create", &eventstypes.ImageCreate{ + Name: image.Name, + Labels: image.Labels, + }); err != nil { + return images.Image{}, err + } + } + return image, nil } @@ -236,6 +250,11 @@ func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths return err } + // Collectible label may be added, if so add to lease + if err := addImageLease(ctx, tx, updated.Name, updated.Labels); err != nil { + return err + } + updated.CreatedAt = createdat if tm := epoch.FromContext(ctx); tm != nil { updated.UpdatedAt = tm.UTC() @@ -247,6 +266,15 @@ func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths return images.Image{}, err } + if publisher := s.db.Publisher(ctx); publisher != nil { + if err := publisher.Publish(ctx, "/images/update", &eventstypes.ImageUpdate{ + Name: updated.Name, + Labels: updated.Labels, + }); err != nil { + return images.Image{}, err + } + } + return updated, nil } @@ -257,12 +285,39 @@ func (s *imageStore) Delete(ctx context.Context, name string, opts ...images.Del return err } - return update(ctx, s.db, func(tx *bolt.Tx) error { + var options images.DeleteOptions + for _, opt := range opts { + if err := opt(ctx, &options); err != nil { + return err + } + } + + err = update(ctx, s.db, func(tx *bolt.Tx) error { bkt := getImagesBucket(tx, namespace) if bkt == nil { return fmt.Errorf("image %q: %w", name, errdefs.ErrNotFound) } + if err := removeImageLease(ctx, tx, name); err != nil { + return err + } + + if options.Target != nil && options.Target.Digest != "" { + ibkt := bkt.Bucket([]byte(name)) + if ibkt == nil { + return fmt.Errorf("image %q: %w", name, errdefs.ErrNotFound) + } + + var check images.Image + if err := readImage(&check, ibkt); err != nil { + return fmt.Errorf("image %q: %w", name, err) + } + + if check.Target.Digest != options.Target.Digest { + return fmt.Errorf("image %q has target %v, not %v: %w", name, check.Target.Digest, options.Target.Digest, errdefs.ErrNotFound) + } + } + if err = bkt.DeleteBucket([]byte(name)); err != nil { if err == bolt.ErrBucketNotFound { err = fmt.Errorf("image %q: %w", name, errdefs.ErrNotFound) @@ -274,6 +329,19 @@ func (s *imageStore) Delete(ctx context.Context, name string, opts ...images.Del return nil }) + if err != nil { + return err + } + + if publisher := s.db.Publisher(ctx); publisher != nil { + if err := publisher.Publish(ctx, "/images/delete", &eventstypes.ImageDelete{ + Name: name, + }); err != nil { + return err + } + } + + return nil } func validateImage(image *images.Image) error { diff --git a/vendor/github.com/containerd/containerd/metadata/leases.go b/vendor/github.com/containerd/containerd/v2/core/metadata/leases.go similarity index 86% rename from vendor/github.com/containerd/containerd/metadata/leases.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/leases.go index 03fa75af34..649d77bc50 100644 --- a/vendor/github.com/containerd/containerd/metadata/leases.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/leases.go @@ -24,11 +24,11 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/metadata/boltutil" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/metadata/boltutil" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/errdefs" digest "github.com/opencontainers/go-digest" bolt "go.etcd.io/bbolt" ) @@ -279,6 +279,20 @@ func (lm *leaseManager) ListResources(ctx context.Context, lease leases.Lease) ( } } + // images resources + if ibkt := topbkt.Bucket(bucketKeyObjectImages); ibkt != nil { + if err := ibkt.ForEach(func(k, _ []byte) error { + rs = append(rs, leases.Resource{ + ID: string(k), + Type: string(bucketKeyObjectImages), + }) + + return nil + }); err != nil { + return err + } + } + // ingest resources if lbkt := topbkt.Bucket(bucketKeyObjectIngests); lbkt != nil { if err := lbkt.ForEach(func(k, _ []byte) error { @@ -461,6 +475,59 @@ func removeIngestLease(ctx context.Context, tx *bolt.Tx, ref string) error { return bkt.Delete([]byte(ref)) } +func addImageLease(ctx context.Context, tx *bolt.Tx, ref string, labels map[string]string) error { + lid, ok := leases.FromContext(ctx) + if !ok { + return nil + } + + // If image doesn't have expiration, it does not need to be leased + if _, ok := labels[string(labelGCExpire)]; !ok { + return nil + } + + namespace, ok := namespaces.Namespace(ctx) + if !ok { + panic("namespace must already be required") + } + + bkt := getBucket(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases, []byte(lid)) + if bkt == nil { + return fmt.Errorf("lease does not exist: %w", errdefs.ErrNotFound) + } + + bkt, err := bkt.CreateBucketIfNotExists(bucketKeyObjectImages) + if err != nil { + return err + } + + if err := bkt.Put([]byte(ref), nil); err != nil { + return err + } + + return nil +} + +func removeImageLease(ctx context.Context, tx *bolt.Tx, ref string) error { + lid, ok := leases.FromContext(ctx) + if !ok { + return nil + } + + namespace, ok := namespaces.Namespace(ctx) + if !ok { + panic("namespace must already be checked") + } + + bkt := getBucket(tx, bucketKeyVersion, []byte(namespace), bucketKeyObjectLeases, []byte(lid), bucketKeyObjectImages) + if bkt == nil { + // Key does not exist so we return nil + return nil + } + + return bkt.Delete([]byte(ref)) +} + func parseLeaseResource(r leases.Resource) ([]string, string, error) { var ( ref = r.ID @@ -470,7 +537,8 @@ func parseLeaseResource(r leases.Resource) ([]string, string, error) { switch k := keys[0]; k { case string(bucketKeyObjectContent), - string(bucketKeyObjectIngests): + string(bucketKeyObjectIngests), + string(bucketKeyObjectImages): if len(keys) != 1 { return nil, "", fmt.Errorf("invalid resource type %s: %w", typ, errdefs.ErrInvalidArgument) diff --git a/vendor/github.com/containerd/containerd/metadata/migrations.go b/vendor/github.com/containerd/containerd/v2/core/metadata/migrations.go similarity index 63% rename from vendor/github.com/containerd/containerd/metadata/migrations.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/migrations.go index 34febdd159..c507875105 100644 --- a/vendor/github.com/containerd/containerd/metadata/migrations.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/migrations.go @@ -16,7 +16,12 @@ package metadata -import bolt "go.etcd.io/bbolt" +import ( + "bytes" + "fmt" + + bolt "go.etcd.io/bbolt" +) type migration struct { schema string @@ -50,6 +55,11 @@ var migrations = []migration{ version: 3, migrate: noOpMigration, }, + { + schema: "v1", + version: 4, + migrate: migrateSandboxes, + }, } // addChildLinks Adds children key to the snapshotters to enforce snapshot @@ -160,6 +170,87 @@ func migrateIngests(tx *bolt.Tx) error { return nil } +// migrateSandboxes moves sandboxes from root bucket into v1 bucket. +func migrateSandboxes(tx *bolt.Tx) error { + v1bkt, err := tx.CreateBucketIfNotExists(bucketKeyVersion) + if err != nil { + return err + } + + deletingBuckets := [][]byte{} + + if merr := tx.ForEach(func(ns []byte, nsbkt *bolt.Bucket) error { + // Skip v1 bucket, even if users created sandboxes in v1 namespace. + if bytes.Equal(bucketKeyVersion, ns) { + return nil + } + + deletingBuckets = append(deletingBuckets, ns) + + allsbbkt := nsbkt.Bucket(bucketKeyObjectSandboxes) + if allsbbkt == nil { + return nil + } + + tnsbkt, err := v1bkt.CreateBucketIfNotExists(ns) + if err != nil { + return fmt.Errorf("failed to create namespace %s in bucket %s: %w", + ns, bucketKeyVersion, err) + } + + tallsbbkt, err := tnsbkt.CreateBucketIfNotExists(bucketKeyObjectSandboxes) + if err != nil { + return fmt.Errorf("failed to create bucket sandboxes in namespace %s: %w", ns, err) + } + + return allsbbkt.ForEachBucket(func(sb []byte) error { + sbbkt := allsbbkt.Bucket(sb) // single sandbox bucket + + tsbbkt, err := tallsbbkt.CreateBucketIfNotExists(sb) + if err != nil { + return fmt.Errorf("failed to create sandbox object %s in namespace %s: %w", + sb, ns, err) + } + + // copy single + if cerr := sbbkt.ForEach(func(key, value []byte) error { + if value == nil { + return nil + } + + return tsbbkt.Put(key, value) + }); cerr != nil { + return cerr + } + + return sbbkt.ForEachBucket(func(subbkt []byte) error { + tsubbkt, err := tsbbkt.CreateBucketIfNotExists(subbkt) + if err != nil { + return fmt.Errorf("failed to create subbucket %s in sandbox %s (namespace %s): %w", + subbkt, sb, ns, err) + } + + return sbbkt.Bucket(subbkt).ForEach(func(key, value []byte) error { + if value == nil { + return fmt.Errorf("unexpected bucket %s", key) + } + return tsubbkt.Put(key, value) + }) + }) + }) + }); merr != nil { + return fmt.Errorf("failed to copy sandboxes into v1 bucket: %w", err) + } + + for _, ns := range deletingBuckets { + derr := tx.DeleteBucket(ns) + if derr != nil { + return fmt.Errorf("failed to cleanup bucket %s in root: %w", ns, err) + } + } + return nil +} + // noOpMigration was for a database change from boltdb/bolt which is no // longer being supported, to go.etcd.io/bbolt which is the currently // maintained repo for boltdb. diff --git a/vendor/github.com/containerd/containerd/metadata/namespaces.go b/vendor/github.com/containerd/containerd/v2/core/metadata/namespaces.go similarity index 95% rename from vendor/github.com/containerd/containerd/metadata/namespaces.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/namespaces.go index 84eb83f273..b3c56e6293 100644 --- a/vendor/github.com/containerd/containerd/metadata/namespaces.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/namespaces.go @@ -21,10 +21,10 @@ import ( "fmt" "strings" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/identifiers" - l "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/pkg/identifiers" + l "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/errdefs" bolt "go.etcd.io/bbolt" ) diff --git a/vendor/github.com/containerd/containerd/metadata/sandbox.go b/vendor/github.com/containerd/containerd/v2/core/metadata/sandbox.go similarity index 82% rename from vendor/github.com/containerd/containerd/metadata/sandbox.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/sandbox.go index 5766647d33..6659b035ca 100644 --- a/vendor/github.com/containerd/containerd/metadata/sandbox.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/sandbox.go @@ -23,16 +23,21 @@ import ( "strings" "time" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/identifiers" - "github.com/containerd/containerd/metadata/boltutil" - "github.com/containerd/containerd/namespaces" - api "github.com/containerd/containerd/sandbox" + "github.com/containerd/containerd/v2/core/metadata/boltutil" + api "github.com/containerd/containerd/v2/core/sandbox" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/identifiers" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/errdefs" "github.com/containerd/typeurl/v2" "go.etcd.io/bbolt" ) +const ( + spanSandboxPrefix = "metadata.sandbox" +) + type sandboxStore struct { db *DB } @@ -46,6 +51,11 @@ func NewSandboxStore(db *DB) api.Store { // Create a sandbox record in the store func (s *sandboxStore) Create(ctx context.Context, sandbox api.Sandbox) (api.Sandbox, error) { + ctx, span := tracing.StartSpan(ctx, + tracing.Name(spanSandboxPrefix, "Create"), + tracing.WithAttribute("sandbox.id", sandbox.ID), + ) + defer span.End() ns, err := namespaces.NamespaceRequired(ctx) if err != nil { return api.Sandbox{}, err @@ -58,7 +68,7 @@ func (s *sandboxStore) Create(ctx context.Context, sandbox api.Sandbox) (api.San return api.Sandbox{}, fmt.Errorf("failed to validate sandbox: %w", err) } - if err := s.db.Update(func(tx *bbolt.Tx) error { + if err := update(ctx, s.db, func(tx *bbolt.Tx) error { parent, err := createSandboxBucket(tx, ns) if err != nil { return fmt.Errorf("create error: %w", err) @@ -68,6 +78,9 @@ func (s *sandboxStore) Create(ctx context.Context, sandbox api.Sandbox) (api.San return fmt.Errorf("write error: %w", err) } + span.SetAttributes( + tracing.Attribute("sandbox.CreatedAt", sandbox.CreatedAt.Format(time.RFC3339)), + ) return nil }); err != nil { return api.Sandbox{}, err @@ -78,6 +91,11 @@ func (s *sandboxStore) Create(ctx context.Context, sandbox api.Sandbox) (api.San // Update the sandbox with the provided sandbox object and fields func (s *sandboxStore) Update(ctx context.Context, sandbox api.Sandbox, fieldpaths ...string) (api.Sandbox, error) { + ctx, span := tracing.StartSpan(ctx, + tracing.Name(spanSandboxPrefix, "Update"), + tracing.WithAttribute("sandbox.id", sandbox.ID), + ) + defer span.End() ns, err := namespaces.NamespaceRequired(ctx) if err != nil { return api.Sandbox{}, err @@ -138,14 +156,14 @@ func (s *sandboxStore) Update(ctx context.Context, sandbox api.Sandbox, fieldpat updated.UpdatedAt = time.Now().UTC() - if err := s.validate(&updated); err != nil { - return err - } - if err := s.write(parent, &updated, true); err != nil { return err } + span.SetAttributes( + tracing.Attribute("sandbox.CreatedAt", updated.CreatedAt.Format(time.RFC3339)), + tracing.Attribute("sandbox.UpdatedAt", updated.UpdatedAt.Format(time.RFC3339)), + ) ret = updated return nil }); err != nil { @@ -231,6 +249,11 @@ func (s *sandboxStore) List(ctx context.Context, fields ...string) ([]api.Sandbo // Delete a sandbox from metadata store using the id func (s *sandboxStore) Delete(ctx context.Context, id string) error { + ctx, span := tracing.StartSpan(ctx, + tracing.Name(spanSandboxPrefix, "Delete"), + tracing.WithAttribute("sandbox.id", id), + ) + defer span.End() ns, err := namespaces.NamespaceRequired(ctx) if err != nil { return err @@ -243,6 +266,9 @@ func (s *sandboxStore) Delete(ctx context.Context, id string) error { } if err := buckets.DeleteBucket([]byte(id)); err != nil { + if err == bbolt.ErrBucketNotFound { + err = errdefs.ErrNotFound + } return fmt.Errorf("failed to delete sandbox %q: %w", id, err) } @@ -255,6 +281,10 @@ func (s *sandboxStore) Delete(ctx context.Context, id string) error { } func (s *sandboxStore) write(parent *bbolt.Bucket, instance *api.Sandbox, overwrite bool) error { + if err := s.validate(instance); err != nil { + return err + } + var ( bucket *bbolt.Bucket err error @@ -267,13 +297,11 @@ func (s *sandboxStore) write(parent *bbolt.Bucket, instance *api.Sandbox, overwr return err } } else { - bucket = parent.Bucket(id) - if bucket != nil { - return fmt.Errorf("sandbox bucket %q already exists: %w", instance.ID, errdefs.ErrAlreadyExists) - } - bucket, err = parent.CreateBucket(id) if err != nil { + if err == bbolt.ErrBucketExists { + return fmt.Errorf("sandbox bucket %q already exists: %w", instance.ID, errdefs.ErrAlreadyExists) + } return err } } @@ -294,6 +322,10 @@ func (s *sandboxStore) write(parent *bbolt.Bucket, instance *api.Sandbox, overwr return err } + if err := bucket.Put(bucketKeySandboxer, []byte(instance.Sandboxer)); err != nil { + return err + } + runtimeBucket, err := bucket.CreateBucketIfNotExists(bucketKeyRuntime) if err != nil { return err @@ -352,6 +384,12 @@ func (s *sandboxStore) read(parent *bbolt.Bucket, id []byte) (api.Sandbox, error if err != nil { return api.Sandbox{}, err } + sandboxer := bucket.Get(bucketKeySandboxer) + if sandboxer == nil { + inst.Sandboxer = "" + } else { + inst.Sandboxer = string(sandboxer) + } return inst, nil } diff --git a/vendor/github.com/containerd/containerd/metadata/snapshot.go b/vendor/github.com/containerd/containerd/v2/core/metadata/snapshot.go similarity index 96% rename from vendor/github.com/containerd/containerd/metadata/snapshot.go rename to vendor/github.com/containerd/containerd/v2/core/metadata/snapshot.go index a44a65cee3..e46a0e9193 100644 --- a/vendor/github.com/containerd/containerd/metadata/snapshot.go +++ b/vendor/github.com/containerd/containerd/v2/core/metadata/snapshot.go @@ -24,17 +24,16 @@ import ( "sync/atomic" "time" + eventstypes "github.com/containerd/containerd/api/events" + "github.com/containerd/containerd/v2/core/metadata/boltutil" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/errdefs" "github.com/containerd/log" bolt "go.etcd.io/bbolt" - - eventstypes "github.com/containerd/containerd/api/events" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/metadata/boltutil" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/snapshots" ) const ( @@ -280,8 +279,8 @@ func (s *snapshotter) Prepare(ctx context.Context, key, parent string, opts ...s return nil, err } - if s.db.dbopts.publisher != nil { - if err := s.db.dbopts.publisher.Publish(ctx, "/snapshot/prepare", &eventstypes.SnapshotPrepare{ + if publisher := s.db.Publisher(ctx); publisher != nil { + if err := publisher.Publish(ctx, "/snapshot/prepare", &eventstypes.SnapshotPrepare{ Key: key, Parent: parent, Snapshotter: s.name, @@ -651,13 +650,15 @@ func (s *snapshotter) Commit(ctx context.Context, name, key string, opts ...snap return err } - if rerr == nil && s.db.dbopts.publisher != nil { - if err := s.db.dbopts.publisher.Publish(ctx, "/snapshot/commit", &eventstypes.SnapshotCommit{ - Key: key, - Name: name, - Snapshotter: s.name, - }); err != nil { - return err + if rerr == nil { + if publisher := s.db.Publisher(ctx); publisher != nil { + if err := publisher.Publish(ctx, "/snapshot/commit", &eventstypes.SnapshotCommit{ + Key: key, + Name: name, + Snapshotter: s.name, + }); err != nil { + return err + } } } @@ -721,8 +722,8 @@ func (s *snapshotter) Remove(ctx context.Context, key string) error { return err } - if s.db.dbopts.publisher != nil { - return s.db.dbopts.publisher.Publish(ctx, "/snapshot/remove", &eventstypes.SnapshotRemove{ + if publisher := s.db.Publisher(ctx); publisher != nil { + return publisher.Publish(ctx, "/snapshot/remove", &eventstypes.SnapshotRemove{ Key: key, Snapshotter: s.name, }) diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/fuse_linux.go b/vendor/github.com/containerd/containerd/v2/core/mount/fuse_linux.go new file mode 100644 index 0000000000..b3a32b682b --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/mount/fuse_linux.go @@ -0,0 +1,50 @@ +/* + 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 mount + +import ( + "os/exec" + + "golang.org/x/sys/unix" +) + +// fuseSuperMagic is defined in statfs(2) +const fuseSuperMagic = 0x65735546 + +func isFUSE(dir string) bool { + var st unix.Statfs_t + if err := unix.Statfs(dir, &st); err != nil { + return false + } + return st.Type == fuseSuperMagic +} + +// unmountFUSE attempts to unmount using fusermount/fusermount3 helper binary. +// +// For FUSE mounts, using these helper binaries is preferred, see: +// https://github.com/containerd/containerd/pull/3765#discussion_r342083514 +func unmountFUSE(target string) error { + var err error + for _, helperBinary := range []string{"fusermount3", "fusermount"} { + cmd := exec.Command(helperBinary, "-u", target) + err = cmd.Run() + if err == nil { + return nil + } + } + return err +} diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/fuse_unsupported.go b/vendor/github.com/containerd/containerd/v2/core/mount/fuse_unsupported.go new file mode 100644 index 0000000000..04de88c2c5 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/mount/fuse_unsupported.go @@ -0,0 +1,30 @@ +//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. +*/ + +package mount + +import "fmt" + +func isFUSE(dir string) bool { + return false +} + +// unmountFUSE is not implemented on this platform +func unmountFUSE(target string) error { + return fmt.Errorf("FUSE is not supported on this platform") +} diff --git a/vendor/github.com/containerd/containerd/mount/lookup_unix.go b/vendor/github.com/containerd/containerd/v2/core/mount/lookup_unix.go similarity index 85% rename from vendor/github.com/containerd/containerd/mount/lookup_unix.go rename to vendor/github.com/containerd/containerd/v2/core/mount/lookup_unix.go index 6fb16f6dd1..90a0d5a5f2 100644 --- a/vendor/github.com/containerd/containerd/mount/lookup_unix.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/lookup_unix.go @@ -20,21 +20,23 @@ package mount import ( "fmt" - "path/filepath" "github.com/moby/sys/mountinfo" ) // Lookup returns the mount info corresponds to the path. func Lookup(dir string) (Info, error) { - dir = filepath.Clean(dir) - - m, err := mountinfo.GetMounts(mountinfo.ParentsFilter(dir)) + resolvedDir, err := CanonicalizePath(dir) if err != nil { - return Info{}, fmt.Errorf("failed to find the mount info for %q: %w", dir, err) + return Info{}, err + } + + m, err := mountinfo.GetMounts(mountinfo.ParentsFilter(resolvedDir)) + if err != nil { + return Info{}, fmt.Errorf("failed to find the mount info for %q: %w", resolvedDir, err) } if len(m) == 0 { - return Info{}, fmt.Errorf("failed to find the mount info for %q", dir) + return Info{}, fmt.Errorf("failed to find the mount info for %q", resolvedDir) } // find the longest matching mount point diff --git a/vendor/github.com/containerd/containerd/mount/lookup_unsupported.go b/vendor/github.com/containerd/containerd/v2/core/mount/lookup_unsupported.go similarity index 100% rename from vendor/github.com/containerd/containerd/mount/lookup_unsupported.go rename to vendor/github.com/containerd/containerd/v2/core/mount/lookup_unsupported.go diff --git a/vendor/github.com/containerd/containerd/mount/losetup_linux.go b/vendor/github.com/containerd/containerd/v2/core/mount/losetup_linux.go similarity index 97% rename from vendor/github.com/containerd/containerd/mount/losetup_linux.go rename to vendor/github.com/containerd/containerd/v2/core/mount/losetup_linux.go index 811288cff3..a08db7a3a2 100644 --- a/vendor/github.com/containerd/containerd/mount/losetup_linux.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/losetup_linux.go @@ -23,8 +23,8 @@ import ( "strings" "time" - kernel "github.com/containerd/containerd/contrib/seccomp/kernelversion" - "github.com/containerd/containerd/pkg/randutil" + "github.com/containerd/containerd/v2/internal/randutil" + kernel "github.com/containerd/containerd/v2/pkg/kernelversion" "golang.org/x/sys/unix" ) diff --git a/vendor/github.com/containerd/containerd/mount/mount.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount.go similarity index 74% rename from vendor/github.com/containerd/containerd/mount/mount.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mount.go index ae7520f980..e8e0fe31c0 100644 --- a/vendor/github.com/containerd/containerd/mount/mount.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount.go @@ -18,11 +18,17 @@ package mount import ( "fmt" + "path/filepath" + "runtime" "strings" + "github.com/containerd/containerd/api/types" "github.com/containerd/continuity/fs" ) +// HasBindMounts This is a flag to conditionally disable code that relies on working bind-mount support, so such code is easier to find across codebase. +const HasBindMounts = runtime.GOOS != "darwin" && runtime.GOOS != "openbsd" + // Mount is the lingua franca of containerd. A mount represents a // serialized mount syscall. Components either emit or consume mounts. type Mount struct { @@ -68,6 +74,18 @@ func UnmountMounts(mounts []Mount, target string, flags int) error { return nil } +// CanonicalizePath makes path absolute and resolves symlinks in it. +// Path must exist. +func CanonicalizePath(path string) (string, error) { + // Abs also does Clean, so we do not need to call it separately + path, err := filepath.Abs(path) + if err != nil { + return "", err + } + + return filepath.EvalSymlinks(path) +} + // ReadOnly returns a boolean value indicating whether this mount has the "ro" // option set. func (m *Mount) ReadOnly() bool { @@ -130,3 +148,33 @@ func readonlyOverlay(opt []string) []string { } return out } + +// ToProto converts from [Mount] to the containerd +// APIs protobuf definition of a Mount. +func ToProto(mounts []Mount) []*types.Mount { + apiMounts := make([]*types.Mount, len(mounts)) + for i, m := range mounts { + apiMounts[i] = &types.Mount{ + Type: m.Type, + Source: m.Source, + Target: m.Target, + Options: m.Options, + } + } + return apiMounts +} + +// FromProto converts from the protobuf definition [types.Mount] to +// [Mount]. +func FromProto(mm []*types.Mount) []Mount { + mounts := make([]Mount, len(mm)) + for i, m := range mm { + mounts[i] = Mount{ + Type: m.Type, + Source: m.Source, + Target: m.Target, + Options: m.Options, + } + } + return mounts +} diff --git a/vendor/github.com/containerd/containerd/plugin/plugin_other.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_darwin.go similarity index 75% rename from vendor/github.com/containerd/containerd/plugin/plugin_other.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mount_darwin.go index 3133a37516..f319d69707 100644 --- a/vendor/github.com/containerd/containerd/plugin/plugin_other.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_darwin.go @@ -1,5 +1,3 @@ -//go:build !go1.8 || windows || !amd64 || static_build || gccgo || no_dynamic_plugins - /* Copyright The containerd Authors. @@ -16,9 +14,11 @@ limitations under the License. */ -package plugin +package mount -func loadPlugins(path string) (int, error) { - // plugins not supported until 1.8 - return 0, nil +import "github.com/containerd/errdefs" + +// Mount to the provided target. +func (m *Mount) mount(target string) error { + return errdefs.ErrNotImplemented } diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/mount_freebsd.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_freebsd.go new file mode 100644 index 0000000000..8dc04d5d6f --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_freebsd.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 mount + +import ( + "errors" + "fmt" + "os/exec" + + "golang.org/x/sys/unix" +) + +// Mount to the provided target. +// +// The "syscall" and "golang.org/x/sys/unix" packages do not define a Mount +// function for FreeBSD, so instead we execute mount(8) and trust it to do +// the right thing +func (m *Mount) mount(target string) error { + // target: "/foo/target" + // command: "mount -o ro -t nullfs /foo/source /foo/merged" + // Note: FreeBSD mount(8) is particular about the order of flags and arguments + var args []string + for _, o := range m.Options { + args = append(args, "-o", o) + } + args = append(args, "-t", m.Type) + args = append(args, m.Source, target) + + infoBeforeMount, err := Lookup(target) + if err != nil { + return err + } + + // cmd.CombinedOutput() may intermittently return ECHILD because of our signal handling in shim. + // See #4387 and wait(2). + const retriesOnECHILD = 10 + for i := 0; i < retriesOnECHILD; i++ { + cmd := exec.Command("mount", args...) + out, err := cmd.CombinedOutput() + if err == nil { + return nil + } + if !errors.Is(err, unix.ECHILD) { + return fmt.Errorf("mount [%v] failed: %q: %w", args, string(out), err) + } + // We got ECHILD, we are not sure whether the mount was successful. + // If the mount ID has changed, we are sure we got some new mount, but still not sure it is fully completed. + // So we attempt to unmount the new mount before retrying. + infoAfterMount, err := Lookup(target) + if err != nil { + return err + } + if infoAfterMount.ID != infoBeforeMount.ID { + _ = unmount(target, 0) + } + } + return fmt.Errorf("mount [%v] failed with ECHILD (retried %d times)", args, retriesOnECHILD) +} diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_linux.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_linux.go new file mode 100644 index 0000000000..d929157d76 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_linux.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 mount + +import ( + "fmt" + "os" + "strconv" + "strings" + "syscall" + + "golang.org/x/sys/unix" +) + +// TODO: Support multiple mappings in future +func parseIDMapping(mapping string) ([]syscall.SysProcIDMap, error) { + parts := strings.Split(mapping, ":") + if len(parts) != 3 { + return nil, fmt.Errorf("user namespace mappings require the format `container-id:host-id:size`") + } + + cID, err := strconv.Atoi(parts[0]) + if err != nil { + return nil, fmt.Errorf("invalid container id for user namespace remapping, %w", err) + } + + hID, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, fmt.Errorf("invalid host id for user namespace remapping, %w", err) + } + + size, err := strconv.Atoi(parts[2]) + if err != nil { + return nil, fmt.Errorf("invalid size for user namespace remapping, %w", err) + } + + if cID < 0 || hID < 0 || size < 0 { + return nil, fmt.Errorf("invalid mapping %s, all IDs and size must be positive integers", mapping) + } + + return []syscall.SysProcIDMap{ + { + ContainerID: cID, + HostID: hID, + Size: size, + }, + }, nil +} + +// IDMapMount applies GID/UID shift according to gidmap/uidmap for target path +func IDMapMount(source, target string, usernsFd int) (err error) { + var ( + attr unix.MountAttr + ) + + attr.Attr_set = unix.MOUNT_ATTR_IDMAP + attr.Attr_clr = 0 + attr.Propagation = 0 + attr.Userns_fd = uint64(usernsFd) + + dFd, err := unix.OpenTree(-int(unix.EBADF), source, uint(unix.OPEN_TREE_CLONE|unix.OPEN_TREE_CLOEXEC|unix.AT_EMPTY_PATH)) + if err != nil { + return fmt.Errorf("Unable to open tree for %s: %w", target, err) + } + + defer unix.Close(dFd) + if err = unix.MountSetattr(dFd, "", unix.AT_EMPTY_PATH, &attr); err != nil { + return fmt.Errorf("Unable to shift GID/UID for %s: %w", target, err) + } + + if err = unix.MoveMount(dFd, "", -int(unix.EBADF), target, unix.MOVE_MOUNT_F_EMPTY_PATH); err != nil { + return fmt.Errorf("Unable to attach mount tree to %s: %w", target, err) + } + return nil +} + +// GetUsernsFD forks the current process and creates a user namespace using +// the specified mappings. +func GetUsernsFD(uidmap, gidmap string) (_usernsFD *os.File, _ error) { + uidMaps, err := parseIDMapping(uidmap) + if err != nil { + return nil, err + } + + gidMaps, err := parseIDMapping(gidmap) + if err != nil { + return nil, err + } + return getUsernsFD(uidMaps, gidMaps) +} diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_utils_linux.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_utils_linux.go new file mode 100644 index 0000000000..373285be8d --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_utils_linux.go @@ -0,0 +1,85 @@ +//go:build go1.23 && 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 mount + +import ( + "fmt" + "os" + "syscall" + + "github.com/containerd/containerd/v2/pkg/sys" + + "golang.org/x/sys/unix" +) + +// getUsernsFD returns pinnable user namespace's file descriptor. +// +// NOTE: The GO runtime uses pidfd to handle subprocess since go1.23. However, +// it has double close issue tracked by [1]. We can't use pidfd directly and +// the GO runtime doesn't export interface to show if it's using pidfd or not. +// So, we call `sys.SupportsPidFD` first and then use `os.Process` directly. +// +// [1]: https://github.com/golang/go/issues/68984 +func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_ *os.File, retErr error) { + if !sys.SupportsPidFD() { + return nil, fmt.Errorf("failed to prevent pid reused issue because pidfd isn't supported") + } + + proc, err := os.StartProcess("/proc/self/exe", []string{"containerd[getUsernsFD]"}, &os.ProcAttr{ + Sys: &syscall.SysProcAttr{ + Cloneflags: unix.CLONE_NEWUSER, + UidMappings: uidMaps, + GidMappings: gidMaps, + // NOTE: It's reexec but it's not heavy because subprocess + // be in PTRACE_TRACEME mode before performing execve. + Ptrace: true, + Pdeathsig: syscall.SIGKILL, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to start noop process for unshare: %w", err) + } + + defer func() { + proc.Kill() + proc.Wait() + }() + + // NOTE: + // + // The usernsFD will hold the userns reference in kernel. Even if the + // child process is reaped, the usernsFD is still valid. + usernsFD, err := os.Open(fmt.Sprintf("/proc/%d/ns/user", proc.Pid)) + if err != nil { + return nil, fmt.Errorf("failed to get userns file descriptor for /proc/%d/user/ns: %w", proc.Pid, err) + } + defer func() { + if retErr != nil { + usernsFD.Close() + } + }() + + // Ensure the child process is still alive. If the err is ESRCH, we + // should return error because we can't guarantee the usernsFD and + // u[g]idmapFile are valid. It's safe to return error and retry. + if err := proc.Signal(syscall.Signal(0)); err != nil { + return nil, fmt.Errorf("failed to ensure child process is alive: %w", err) + } + return usernsFD, nil +} diff --git a/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_utils_linux_go122.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_utils_linux_go122.go new file mode 100644 index 0000000000..669f395d20 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_idmapped_utils_linux_go122.go @@ -0,0 +1,93 @@ +//go:build !go1.23 && 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 mount + +import ( + "fmt" + "os" + "syscall" + + "github.com/containerd/containerd/v2/pkg/sys" + + "golang.org/x/sys/unix" +) + +// getUsernsFD returns pinnable user namespace's file descriptor. +func getUsernsFD(uidMaps, gidMaps []syscall.SysProcIDMap) (_ *os.File, retErr error) { + var pidfd int + + proc, err := os.StartProcess("/proc/self/exe", []string{"containerd[getUsernsFD]"}, &os.ProcAttr{ + Sys: &syscall.SysProcAttr{ + Cloneflags: unix.CLONE_NEWUSER, + UidMappings: uidMaps, + GidMappings: gidMaps, + // NOTE: It's reexec but it's not heavy because subprocess + // be in PTRACE_TRACEME mode before performing execve. + Ptrace: true, + Pdeathsig: syscall.SIGKILL, + PidFD: &pidfd, + }, + }) + if err != nil { + return nil, fmt.Errorf("failed to start noop process for unshare: %w", err) + } + + if pidfd == -1 || !sys.SupportsPidFD() { + proc.Kill() + proc.Wait() + return nil, fmt.Errorf("failed to prevent pid reused issue because pidfd isn't supported") + } + + pidFD := os.NewFile(uintptr(pidfd), "pidfd") + defer func() { + unix.PidfdSendSignal(int(pidFD.Fd()), unix.SIGKILL, nil, 0) + + pidfdWaitid(pidFD) + + pidFD.Close() + }() + + // NOTE: + // + // The usernsFD will hold the userns reference in kernel. Even if the + // child process is reaped, the usernsFD is still valid. + usernsFD, err := os.Open(fmt.Sprintf("/proc/%d/ns/user", proc.Pid)) + if err != nil { + return nil, fmt.Errorf("failed to get userns file descriptor for /proc/%d/user/ns: %w", proc.Pid, err) + } + defer func() { + if retErr != nil { + usernsFD.Close() + } + }() + + // Ensure the child process is still alive. If the err is ESRCH, we + // should return error because we can't guarantee the usernsFD and + // u[g]idmapFile are valid. It's safe to return error and retry. + if err := unix.PidfdSendSignal(int(pidFD.Fd()), 0, nil, 0); err != nil { + return nil, fmt.Errorf("failed to ensure child process is alive: %w", err) + } + return usernsFD, nil +} + +func pidfdWaitid(pidFD *os.File) error { + return sys.IgnoringEINTR(func() error { + return unix.Waitid(unix.P_PIDFD, int(pidFD.Fd()), nil, unix.WEXITED, nil) + }) +} diff --git a/vendor/github.com/containerd/containerd/mount/mount_linux.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go similarity index 67% rename from vendor/github.com/containerd/containerd/mount/mount_linux.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go index 402def9c79..a14d545fd0 100644 --- a/vendor/github.com/containerd/containerd/mount/mount_linux.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_linux.go @@ -22,14 +22,24 @@ import ( "os" "os/exec" "path" + "path/filepath" "runtime" + "strconv" "strings" - "time" + "github.com/containerd/log" "github.com/moby/sys/userns" "golang.org/x/sys/unix" ) +type mountOpt struct { + flags int + data []string + losetup bool + uidmap string + gidmap string +} + var ( pagesize = 4096 allowedHelperBinaries = []string{"mount.fuse", "mount.fuse3"} @@ -39,6 +49,34 @@ func init() { pagesize = os.Getpagesize() } +// prepareIDMappedOverlay is a helper function to obtain +// actual "lowerdir=..." mount options. It creates and +// applies id mapping for each lowerdir. +// +// It returns: +// 1. New options that include new "lowedir=..." mount option. +// 2. "Clean up" function -- it should be called as a defer one before +// checking for error, because if do the second and avoid calling "clean up", +// you're going to have "dirty" setup -- there's no guarantee that those +// temporary mount points for lowedirs will be cleaned properly. +// 3. Error -- nil if everything's fine, otherwise an error. +func prepareIDMappedOverlay(usernsFd int, options []string) ([]string, func(), error) { + lowerIdx, lowerDirs := findOverlayLowerdirs(options) + if lowerIdx == -1 { + return options, nil, fmt.Errorf("failed to parse overlay lowerdir's from given options") + } + + tmpLowerdirs, idMapCleanUp, err := doPrepareIDMappedOverlay(lowerDirs, usernsFd) + if err != nil { + return options, idMapCleanUp, fmt.Errorf("failed to create idmapped mount: %w", err) + } + + options = append(options[:lowerIdx], options[lowerIdx+1:]...) + options = append(options, fmt.Sprintf("lowerdir=%s", strings.Join(tmpLowerdirs, ":"))) + + return options, idMapCleanUp, nil +} + // Mount to the provided target path. // // If m.Type starts with "fuse." or "fuse3.", "mount.fuse" or "mount.fuse3" @@ -52,45 +90,79 @@ func (m *Mount) mount(target string) (err error) { } } var ( - chdir string - options = m.Options + chdir string + recalcOpt bool + usernsFd *os.File + options = m.Options ) + opt := parseMountOptions(options) + // The only remapping of both GID and UID is supported + if opt.uidmap != "" && opt.gidmap != "" { + if usernsFd, err = GetUsernsFD(opt.uidmap, opt.gidmap); err != nil { + return err + } + defer usernsFd.Close() + + // overlay expects lowerdir's to be remapped instead + if m.Type == "overlay" { + var ( + userNsCleanUp func() + ) + options, userNsCleanUp, err = prepareIDMappedOverlay(int(usernsFd.Fd()), options) + defer userNsCleanUp() + + if err != nil { + return fmt.Errorf("failed to prepare idmapped overlay: %w", err) + } + // To not meet concurrency issues while using the same lowedirs + // for different containers, replace them by temporary directories, + if optionsSize(options) >= pagesize-512 { + recalcOpt = true + } else { + opt = parseMountOptions(options) + } + } + } + // avoid hitting one page limit of mount argument buffer // // NOTE: 512 is a buffer during pagesize check. if m.Type == "overlay" && optionsSize(options) >= pagesize-512 { chdir, options = compactLowerdirOption(options) + // recalculate opt in case of lowerdirs have been replaced + // by idmapped ones OR idmapped mounts' not used/supported. + if recalcOpt || (opt.uidmap == "" || opt.gidmap == "") { + opt = parseMountOptions(options) + } } - flags, data, losetup := parseMountOptions(options) - // propagation types. const ptypes = unix.MS_SHARED | unix.MS_PRIVATE | unix.MS_SLAVE | unix.MS_UNBINDABLE // Ensure propagation type change flags aren't included in other calls. - oflags := flags &^ ptypes + oflags := opt.flags &^ ptypes var loopParams LoopParams - if losetup { + if opt.losetup { loopParams = LoopParams{ Readonly: oflags&unix.MS_RDONLY == unix.MS_RDONLY, Autoclear: true, } - loopParams.Direct, data = hasDirectIO(data) + loopParams.Direct, opt.data = hasDirectIO(opt.data) } - dataInStr := strings.Join(data, ",") + dataInStr := strings.Join(opt.data, ",") if len(dataInStr) > pagesize { return errors.New("mount options is too long") } - // In the case of remounting with changed data (data != ""), need to call mount (moby/moby#34077). - if flags&unix.MS_REMOUNT == 0 || dataInStr != "" { + // In the case of remounting with changed data (dataInStr != ""), need to call mount (moby/moby#34077). + if opt.flags&unix.MS_REMOUNT == 0 || dataInStr != "" { // Initial call applying all non-propagation flags for mount // or remount with changed data source := m.Source - if losetup { + if opt.losetup { loFile, err := setupLoop(m.Source, loopParams) if err != nil { return err @@ -105,10 +177,10 @@ func (m *Mount) mount(target string) (err error) { } } - if flags&ptypes != 0 { + if opt.flags&ptypes != 0 { // Change the propagation type. const pflags = ptypes | unix.MS_REC | unix.MS_SILENT - if err := unix.Mount("", target, "", uintptr(flags&pflags), ""); err != nil { + if err := unix.Mount("", target, "", uintptr(opt.flags&pflags), ""); err != nil { return err } } @@ -131,6 +203,13 @@ func (m *Mount) mount(target string) (err error) { // Remount the bind to apply read only. return unix.Mount("", target, "", uintptr(oflags|unprivFlags|unix.MS_REMOUNT), "") } + + // remap non-overlay mount point + if opt.uidmap != "" && opt.gidmap != "" && m.Type != "overlay" { + if err := IDMapMount(target, target, int(usernsFd.Fd())); err != nil { + return err + } + } return nil } @@ -165,102 +244,50 @@ func getUnprivilegedMountFlags(path string) (int, error) { return flags, nil } -// Unmount the provided mount path with the flags -func Unmount(target string, flags int) error { - if err := unmount(target, flags); err != nil && err != unix.EINVAL { - return err +func doPrepareIDMappedOverlay(lowerDirs []string, usernsFd int) (tmpLowerDirs []string, _ func(), _ error) { + td, err := os.MkdirTemp(tempMountLocation, "ovl-idmapped") + if err != nil { + return nil, nil, err } - return nil -} - -// fuseSuperMagic is defined in statfs(2) -const fuseSuperMagic = 0x65735546 - -func isFUSE(dir string) bool { - var st unix.Statfs_t - if err := unix.Statfs(dir, &st); err != nil { - return false - } - return st.Type == fuseSuperMagic -} - -// unmountFUSE attempts to unmount using fusermount/fusermount3 helper binary. -// -// For FUSE mounts, using these helper binaries is preferred, see: -// https://github.com/containerd/containerd/pull/3765#discussion_r342083514 -func unmountFUSE(target string) error { - var err error - for _, helperBinary := range []string{"fusermount3", "fusermount"} { - cmd := exec.Command(helperBinary, "-u", target) - err = cmd.Run() - if err == nil { - return nil - } - } - return err -} - -func unmount(target string, flags int) error { - if isFUSE(target) { - if err := unmountFUSE(target); err == nil { - return nil - } - } - for i := 0; i < 50; i++ { - if err := unix.Unmount(target, flags); err != nil { - switch err { - case unix.EBUSY: - time.Sleep(50 * time.Millisecond) + cleanUp := func() { + for _, lowerDir := range tmpLowerDirs { + // Do a detached unmount so even if the resource is busy, the mount will be + // gone (eventually) and we can safely delete the directory too. + if err := unix.Unmount(lowerDir, unix.MNT_DETACH); err != nil { + log.L.WithError(err).Warnf("failed to unmount temp lowerdir %s", lowerDir) continue - default: - return err + } + // Using os.Remove() so if it's not empty, we don't delete files in the + // rootfs. + if err := os.Remove(lowerDir); err != nil { + log.L.WithError(err).Warnf("failed to remove temporary overlay lowerdir's") } } - return nil - } - return fmt.Errorf("failed to unmount target %s: %w", target, unix.EBUSY) -} -// UnmountAll repeatedly unmounts the given mount point until there -// are no mounts remaining (EINVAL is returned by mount), which is -// useful for undoing a stack of mounts on the same mount point. -// UnmountAll all is noop when the first argument is an empty string. -// This is done when the containerd client did not specify any rootfs -// mounts (e.g. because the rootfs is managed outside containerd) -// UnmountAll is noop when the mount path does not exist. -func UnmountAll(mount string, flags int) error { - if mount == "" { - return nil - } - if _, err := os.Stat(mount); os.IsNotExist(err) { - return nil - } - - for { - if err := unmount(mount, flags); err != nil { - // EINVAL is returned if the target is not a - // mount point, indicating that we are - // done. It can also indicate a few other - // things (such as invalid flags) which we - // unfortunately end up squelching here too. - if err == unix.EINVAL { - return nil - } - return err + // This dir should be empty now. Otherwise, we don't do anything. + if err := os.Remove(filepath.Join(tmpLowerDirs[0], "..")); err != nil { + log.L.WithError(err).Infof("failed to remove temporary overlay dir") } } + for i, lowerDir := range lowerDirs { + tmpLowerDir := filepath.Join(td, strconv.Itoa(i)) + tmpLowerDirs = append(tmpLowerDirs, tmpLowerDir) + + if err = os.MkdirAll(tmpLowerDir, 0700); err != nil { + return nil, cleanUp, fmt.Errorf("failed to create temporary dir: %w", err) + } + if err = IDMapMount(lowerDir, tmpLowerDir, usernsFd); err != nil { + return nil, cleanUp, err + } + } + return tmpLowerDirs, cleanUp, nil } // parseMountOptions takes fstab style mount options and parses them for // use with a standard mount() syscall -func parseMountOptions(options []string) (int, []string, bool) { - var ( - flag int - losetup bool - data []string - ) +func parseMountOptions(options []string) (opt mountOpt) { loopOpt := "loop" - flags := map[string]struct { + flagsMap := map[string]struct { clear bool flag int }{ @@ -294,19 +321,23 @@ func parseMountOptions(options []string) (int, []string, bool) { // If the option does not exist in the flags table or the flag // is not supported on the platform, // then it is a data value for a specific fs type - if f, exists := flags[o]; exists && f.flag != 0 { + if f, exists := flagsMap[o]; exists && f.flag != 0 { if f.clear { - flag &^= f.flag + opt.flags &^= f.flag } else { - flag |= f.flag + opt.flags |= f.flag } } else if o == loopOpt { - losetup = true + opt.losetup = true + } else if strings.HasPrefix(o, "uidmap=") { + opt.uidmap = strings.TrimPrefix(o, "uidmap=") + } else if strings.HasPrefix(o, "gidmap=") { + opt.gidmap = strings.TrimPrefix(o, "gidmap=") } else { - data = append(data, o) + opt.data = append(opt.data, o) } } - return flag, data, losetup + return } func hasDirectIO(opts []string) (bool, []string) { @@ -337,13 +368,16 @@ func compactLowerdirOption(opts []string) (string, []string) { // in order to avoid to get snapshots/x, should be back to parent dir. // however, there is assumption that the common dir is ${root}/io.containerd.v1.overlayfs/snapshots. commondir = path.Dir(commondir) - if commondir == "/" { + if commondir == "/" || commondir == "." { return "", opts } commondir = commondir + "/" newdirs := make([]string, 0, len(dirs)) for _, dir := range dirs { + if len(dir) <= len(commondir) { + return "", opts + } newdirs = append(newdirs, dir[len(commondir):]) } @@ -491,5 +525,5 @@ func (m *Mount) mountWithHelper(helperBinary, typePrefix, target string) error { _ = unmount(target, 0) } } - return fmt.Errorf("mount helper [%s %v] failed with ECHILD (retired %d times)", helperBinary, args, retriesOnECHILD) + return fmt.Errorf("mount helper [%s %v] failed with ECHILD (retried %d times)", helperBinary, args, retriesOnECHILD) } diff --git a/vendor/github.com/containerd/containerd/mount/mount_freebsd.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_unix.go similarity index 57% rename from vendor/github.com/containerd/containerd/mount/mount_freebsd.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mount_unix.go index 3a5c09353c..848464010d 100644 --- a/vendor/github.com/containerd/containerd/mount/mount_freebsd.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_unix.go @@ -1,3 +1,5 @@ +//go:build !windows && !openbsd + /* Copyright The containerd Authors. @@ -17,76 +19,68 @@ package mount import ( - "errors" "fmt" "os" - "os/exec" + "sort" "time" + "github.com/moby/sys/mountinfo" "golang.org/x/sys/unix" ) -var ( - // ErrNotImplementOnUnix is returned for methods that are not implemented - ErrNotImplementOnUnix = errors.New("not implemented under unix") -) - -// Mount to the provided target. -// -// The "syscall" and "golang.org/x/sys/unix" packages do not define a Mount -// function for FreeBSD, so instead we execute mount(8) and trust it to do -// the right thing -func (m *Mount) mount(target string) error { - // target: "/foo/target" - // command: "mount -o ro -t nullfs /foo/source /foo/merged" - // Note: FreeBSD mount(8) is particular about the order of flags and arguments - var args []string - for _, o := range m.Options { - args = append(args, "-o", o) +// UnmountRecursive unmounts the target and all mounts underneath, starting +// with the deepest mount first. +func UnmountRecursive(target string, flags int) error { + if target == "" { + return nil } - args = append(args, "-t", m.Type) - args = append(args, m.Source, target) - infoBeforeMount, err := Lookup(target) + target, err := CanonicalizePath(target) + if err != nil { + if os.IsNotExist(err) { + err = nil + } + return err + } + + mounts, err := mountinfo.GetMounts(mountinfo.PrefixFilter(target)) if err != nil { return err } - // cmd.CombinedOutput() may intermittently return ECHILD because of our signal handling in shim. - // See #4387 and wait(2). - const retriesOnECHILD = 10 - for i := 0; i < retriesOnECHILD; i++ { - cmd := exec.Command("mount", args...) - out, err := cmd.CombinedOutput() - if err == nil { - return nil - } - if !errors.Is(err, unix.ECHILD) { - return fmt.Errorf("mount [%v] failed: %q: %w", args, string(out), err) - } - // We got ECHILD, we are not sure whether the mount was successful. - // If the mount ID has changed, we are sure we got some new mount, but still not sure it is fully completed. - // So we attempt to unmount the new mount before retrying. - infoAfterMount, err := Lookup(target) - if err != nil { - return err - } - if infoAfterMount.ID != infoBeforeMount.ID { - _ = unmount(target, 0) - } + targetSet := make(map[string]struct{}) + for _, m := range mounts { + targetSet[m.Mountpoint] = struct{}{} } - return fmt.Errorf("mount [%v] failed with ECHILD (retired %d times)", args, retriesOnECHILD) -} -// Unmount the provided mount path with the flags -func Unmount(target string, flags int) error { - if err := unmount(target, flags); err != nil && err != unix.EINVAL { - return err + var targets []string + for m := range targetSet { + targets = append(targets, m) + } + + // Make the deepest mount be first + sort.SliceStable(targets, func(i, j int) bool { + return len(targets[i]) > len(targets[j]) + }) + + for i, target := range targets { + if err := UnmountAll(target, flags); err != nil { + if i == len(targets)-1 { // last mount + return err + } + } } return nil } func unmount(target string, flags int) error { + if isFUSE(target) { + // TODO: Why error is ignored? + // Shouldn't this just be unconditional "return unmountFUSE(target)"? + if err := unmountFUSE(target); err == nil { + return nil + } + } for i := 0; i < 50; i++ { if err := unix.Unmount(target, flags); err != nil { switch err { @@ -102,6 +96,14 @@ func unmount(target string, flags int) error { return fmt.Errorf("failed to unmount target %s: %w", target, unix.EBUSY) } +// Unmount the provided mount path with the flags +func Unmount(target string, flags int) error { + if err := unmount(target, flags); err != nil && err != unix.EINVAL { + return err + } + return nil +} + // UnmountAll repeatedly unmounts the given mount point until there // are no mounts remaining (EINVAL is returned by mount), which is // useful for undoing a stack of mounts on the same mount point. diff --git a/vendor/github.com/containerd/containerd/mount/mount_unsupported.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_unsupported.go similarity index 76% rename from vendor/github.com/containerd/containerd/mount/mount_unsupported.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mount_unsupported.go index 894467a993..af9e6b3370 100644 --- a/vendor/github.com/containerd/containerd/mount/mount_unsupported.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_unsupported.go @@ -1,4 +1,4 @@ -//go:build darwin || openbsd +//go:build openbsd /* Copyright The containerd Authors. @@ -18,29 +18,24 @@ package mount -import "errors" - -var ( - // ErrNotImplementOnUnix is returned for methods that are not implemented - ErrNotImplementOnUnix = errors.New("not implemented under unix") -) +import "github.com/containerd/errdefs" // Mount is not implemented on this platform func (m *Mount) mount(target string) error { - return ErrNotImplementOnUnix + return errdefs.ErrNotImplemented } // Unmount is not implemented on this platform func Unmount(mount string, flags int) error { - return ErrNotImplementOnUnix + return errdefs.ErrNotImplemented } // UnmountAll is not implemented on this platform func UnmountAll(mount string, flags int) error { - return ErrNotImplementOnUnix + return errdefs.ErrNotImplemented } // UnmountRecursive is not implemented on this platform func UnmountRecursive(mount string, flags int) error { - return ErrNotImplementOnUnix + return errdefs.ErrNotImplemented } diff --git a/vendor/github.com/containerd/containerd/mount/mount_windows.go b/vendor/github.com/containerd/containerd/v2/core/mount/mount_windows.go similarity index 97% rename from vendor/github.com/containerd/containerd/mount/mount_windows.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mount_windows.go index 91ac6968d2..925cde0a0b 100644 --- a/vendor/github.com/containerd/containerd/mount/mount_windows.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/mount_windows.go @@ -33,11 +33,6 @@ import ( const sourceStreamName = "containerd.io-source" -var ( - // ErrNotImplementOnWindows is returned when an action is not implemented for windows - ErrNotImplementOnWindows = errors.New("not implemented under windows") -) - // Mount to the provided target. func (m *Mount) mount(target string) (retErr error) { if m.Type != "windows-layer" { diff --git a/vendor/github.com/containerd/containerd/mount/mountinfo.go b/vendor/github.com/containerd/containerd/v2/core/mount/mountinfo.go similarity index 100% rename from vendor/github.com/containerd/containerd/mount/mountinfo.go rename to vendor/github.com/containerd/containerd/v2/core/mount/mountinfo.go diff --git a/vendor/github.com/containerd/containerd/mount/temp.go b/vendor/github.com/containerd/containerd/v2/core/mount/temp.go similarity index 100% rename from vendor/github.com/containerd/containerd/mount/temp.go rename to vendor/github.com/containerd/containerd/v2/core/mount/temp.go diff --git a/vendor/github.com/containerd/containerd/mount/temp_unix.go b/vendor/github.com/containerd/containerd/v2/core/mount/temp_unix.go similarity index 89% rename from vendor/github.com/containerd/containerd/mount/temp_unix.go rename to vendor/github.com/containerd/containerd/v2/core/mount/temp_unix.go index 5ddd2cd160..8845e47aa1 100644 --- a/vendor/github.com/containerd/containerd/mount/temp_unix.go +++ b/vendor/github.com/containerd/containerd/v2/core/mount/temp_unix.go @@ -20,7 +20,6 @@ package mount import ( "os" - "path/filepath" "sort" "github.com/moby/sys/mountinfo" @@ -28,15 +27,13 @@ import ( // SetTempMountLocation sets the temporary mount location func SetTempMountLocation(root string) error { - root, err := filepath.Abs(root) + err := os.MkdirAll(root, 0700) if err != nil { return err } - if err := os.MkdirAll(root, 0700); err != nil { - return err - } - tempMountLocation = root - return nil + // We need to pass canonicalized path to mountinfo.PrefixFilter in CleanupTempMounts + tempMountLocation, err = CanonicalizePath(root) + return err } // CleanupTempMounts all temp mounts and remove the directories @@ -45,6 +42,7 @@ func CleanupTempMounts(flags int) (warnings []error, err error) { if err != nil { return nil, err } + // Make the deepest mount be first sort.Slice(mounts, func(i, j int) bool { return len(mounts[i].Mountpoint) > len(mounts[j].Mountpoint) diff --git a/vendor/github.com/containerd/containerd/mount/temp_unsupported.go b/vendor/github.com/containerd/containerd/v2/core/mount/temp_unsupported.go similarity index 100% rename from vendor/github.com/containerd/containerd/mount/temp_unsupported.go rename to vendor/github.com/containerd/containerd/v2/core/mount/temp_unsupported.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/auth/fetch.go similarity index 86% rename from vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/auth/fetch.go index 244e03509a..16ea609a13 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/auth/fetch.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/auth/fetch.go @@ -26,8 +26,9 @@ import ( "strings" "time" - remoteserrors "github.com/containerd/containerd/remotes/errors" - "github.com/containerd/containerd/version" + remoteserrors "github.com/containerd/containerd/v2/core/remotes/errors" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/containerd/v2/version" "github.com/containerd/log" ) @@ -86,15 +87,19 @@ type TokenOptions struct { // OAuthTokenResponse is response from fetching token with a OAuth POST request type OAuthTokenResponse struct { - AccessToken string `json:"access_token"` - RefreshToken string `json:"refresh_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` - Scope string `json:"scope"` + AccessToken string `json:"access_token"` + RefreshToken string `json:"refresh_token"` + ExpiresInSeconds int `json:"expires_in"` + IssuedAt time.Time `json:"issued_at"` + Scope string `json:"scope"` } // FetchTokenWithOAuth fetches a token using a POST request func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http.Header, clientID string, to TokenOptions) (*OAuthTokenResponse, error) { + c := *client + client = &c + tracing.UpdateHTTPClient(client, tracing.Name("remotes.docker.resolver", "FetchTokenWithOAuth")) + form := url.Values{} if len(to.Scopes) > 0 { form.Set("scope", strings.Join(to.Scopes, " ")) @@ -152,15 +157,19 @@ func FetchTokenWithOAuth(ctx context.Context, client *http.Client, headers http. // FetchTokenResponse is response from fetching token with GET request type FetchTokenResponse struct { - Token string `json:"token"` - AccessToken string `json:"access_token"` - ExpiresIn int `json:"expires_in"` - IssuedAt time.Time `json:"issued_at"` - RefreshToken string `json:"refresh_token"` + Token string `json:"token"` + AccessToken string `json:"access_token"` + ExpiresInSeconds int `json:"expires_in"` + IssuedAt time.Time `json:"issued_at"` + RefreshToken string `json:"refresh_token"` } // FetchToken fetches a token using a GET request func FetchToken(ctx context.Context, client *http.Client, headers http.Header, to TokenOptions) (*FetchTokenResponse, error) { + c := *client + client = &c + tracing.UpdateHTTPClient(client, tracing.Name("remotes.docker.resolver", "FetchToken")) + req, err := http.NewRequestWithContext(ctx, http.MethodGet, to.Realm, nil) if err != nil { return nil, err diff --git a/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/auth/parse.go similarity index 98% rename from vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/auth/parse.go index e4529a7761..6ca935158e 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/auth/parse.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/auth/parse.go @@ -49,7 +49,7 @@ type byScheme []Challenge func (bs byScheme) Len() int { return len(bs) } func (bs byScheme) Swap(i, j int) { bs[i], bs[j] = bs[j], bs[i] } -// Sort in priority order: token > digest > basic +// Less sorts in priority order: token > digest > basic func (bs byScheme) Less(i, j int) bool { return bs[i].Scheme > bs[j].Scheme } // Octet types from RFC 2616. diff --git a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/authorizer.go similarity index 90% rename from vendor/github.com/containerd/containerd/remotes/docker/authorizer.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/authorizer.go index 2bf388e8cb..01fc792fa4 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/authorizer.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/authorizer.go @@ -24,12 +24,12 @@ import ( "net/http" "strings" "sync" + "time" + "github.com/containerd/containerd/v2/core/remotes/docker/auth" + remoteerrors "github.com/containerd/containerd/v2/core/remotes/errors" + "github.com/containerd/errdefs" "github.com/containerd/log" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/remotes/docker/auth" - remoteerrors "github.com/containerd/containerd/remotes/errors" ) type dockerAuthorizer struct { @@ -206,9 +206,10 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R // authResult is used to control limit rate. type authResult struct { sync.WaitGroup - token string - refreshToken string - err error + token string + refreshToken string + expirationTime *time.Time + err error } // authHandler is used to handle auth request per registry server. @@ -271,8 +272,12 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st // Docs: https://docs.docker.com/registry/spec/auth/scope scoped := strings.Join(to.Scopes, " ") + // Keep track of the expiration time of cached bearer tokens so they can be + // refreshed when they expire without a server roundtrip. + var expirationTime *time.Time + ah.Lock() - if r, exist := ah.scopedTokens[scoped]; exist { + if r, exist := ah.scopedTokens[scoped]; exist && (r.expirationTime == nil || r.expirationTime.After(time.Now())) { ah.Unlock() r.Wait() return r.token, r.refreshToken, r.err @@ -286,7 +291,7 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st defer func() { token = fmt.Sprintf("Bearer %s", token) - r.token, r.refreshToken, r.err = token, refreshToken, err + r.token, r.refreshToken, r.err, r.expirationTime = token, refreshToken, err, expirationTime r.Done() }() @@ -312,6 +317,7 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st if err != nil { return "", "", err } + expirationTime = getExpirationTime(resp.ExpiresInSeconds) return resp.Token, resp.RefreshToken, nil } log.G(ctx).WithFields(log.Fields{ @@ -321,6 +327,7 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st } return "", "", err } + expirationTime = getExpirationTime(resp.ExpiresInSeconds) return resp.AccessToken, resp.RefreshToken, nil } // do request anonymously @@ -328,9 +335,18 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st if err != nil { return "", "", fmt.Errorf("failed to fetch anonymous token: %w", err) } + expirationTime = getExpirationTime(resp.ExpiresInSeconds) return resp.Token, resp.RefreshToken, nil } +func getExpirationTime(expiresInSeconds int) *time.Time { + if expiresInSeconds <= 0 { + return nil + } + expirationTime := time.Now().Add(time.Duration(expiresInSeconds) * time.Second) + return &expirationTime +} + func invalidAuthorization(ctx context.Context, c auth.Challenge, responses []*http.Response) (retry bool, _ error) { errStr := c.Parameters["error"] if errStr == "" { diff --git a/vendor/github.com/containerd/containerd/remotes/docker/config/config_unix.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/config_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/config/config_unix.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/config_unix.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/config/config_windows.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/config_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/config/config_windows.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/config_windows.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/config/docker_fuzzer_internal.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/docker_fuzzer_internal.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/config/docker_fuzzer_internal.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/docker_fuzzer_internal.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/config/hosts.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/hosts.go similarity index 88% rename from vendor/github.com/containerd/containerd/remotes/docker/config/hosts.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/hosts.go index c138c952e4..86ea23238c 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/config/hosts.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/config/hosts.go @@ -20,7 +20,6 @@ package config import ( "context" "crypto/tls" - "errors" "fmt" "net" "net/http" @@ -28,15 +27,15 @@ import ( "os" "path" "path/filepath" - "sort" "strings" "time" + "github.com/containerd/errdefs" "github.com/containerd/log" - "github.com/pelletier/go-toml" + "github.com/pelletier/go-toml/v2" + tomlu "github.com/pelletier/go-toml/v2/unstable" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker" ) // UpdateClientFunc is a function that lets you to amend http Client behavior used by registry clients. @@ -206,29 +205,27 @@ func ConfigureHosts(ctx context.Context, options HostOptions) docker.RegistryHos } } - if host.clientPairs != nil { - for _, pair := range host.clientPairs { - certPEMBlock, err := os.ReadFile(pair[0]) - if err != nil { - return nil, fmt.Errorf("unable to read CERT file %q: %w", pair[0], err) - } - var keyPEMBlock []byte - if pair[1] != "" { - keyPEMBlock, err = os.ReadFile(pair[1]) - if err != nil { - return nil, fmt.Errorf("unable to read CERT file %q: %w", pair[1], err) - } - } else { - // Load key block from same PEM file - keyPEMBlock = certPEMBlock - } - cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock) - if err != nil { - return nil, fmt.Errorf("failed to load X509 key pair: %w", err) - } - - tlsConfig.Certificates = append(tlsConfig.Certificates, cert) + for _, pair := range host.clientPairs { + certPEMBlock, err := os.ReadFile(pair[0]) + if err != nil { + return nil, fmt.Errorf("unable to read CERT file %q: %w", pair[0], err) } + var keyPEMBlock []byte + if pair[1] != "" { + keyPEMBlock, err = os.ReadFile(pair[1]) + if err != nil { + return nil, fmt.Errorf("unable to read CERT file %q: %w", pair[1], err) + } + } else { + // Load key block from same PEM file + keyPEMBlock = certPEMBlock + } + cert, err := tls.X509KeyPair(certPEMBlock, keyPEMBlock) + if err != nil { + return nil, fmt.Errorf("failed to load X509 key pair: %w", err) + } + + tlsConfig.Certificates = append(tlsConfig.Certificates, cert) } c := *client @@ -312,7 +309,7 @@ func loadHostDir(ctx context.Context, hostsDir string) ([]hostConfig, error) { hosts, err := parseHostsFile(hostsDir, b) if err != nil { - log.G(ctx).WithError(err).Error("failed to decode hosts.toml") + log.G(ctx).WithError(err).Errorf("failed to decode %s", filepath.Join(hostsDir, "hosts.toml")) // Fallback to checking certificate files return loadCertFiles(ctx, hostsDir) } @@ -359,17 +356,13 @@ type hostFileConfig struct { } func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) { - tree, err := toml.LoadBytes(b) + orderedHosts, err := getSortedHosts(b) if err != nil { - return nil, fmt.Errorf("failed to parse TOML: %w", err) + return nil, err } - // HACK: we want to keep toml parsing structures private in this package, however go-toml ignores private embedded types. - // so we remap it to a public type within the func body, so technically it's public, but not possible to import elsewhere. - type HostFileConfig = hostFileConfig - c := struct { - HostFileConfig + hostFileConfig // Server specifies the default server. When `host` is // also specified, those hosts are tried first. Server string `toml:"server"` @@ -377,16 +370,11 @@ func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) { HostConfigs map[string]hostFileConfig `toml:"host"` }{} - orderedHosts, err := getSortedHosts(tree) - if err != nil { - return nil, err - } - var ( hosts []hostConfig ) - if err := tree.Unmarshal(&c); err != nil { + if err := toml.Unmarshal(b, &c); err != nil { return nil, err } @@ -402,7 +390,7 @@ func parseHostsFile(baseDir string, b []byte) ([]hostConfig, error) { } // Parse root host config and append it as the last element - parsed, err := parseHostConfig(c.Server, baseDir, c.HostFileConfig) + parsed, err := parseHostConfig(c.Server, baseDir, c.hostFileConfig) if err != nil { return nil, err } @@ -527,24 +515,41 @@ func parseHostConfig(server string, baseDir string, config hostFileConfig) (host return result, nil } -// getSortedHosts returns the list of hosts as they defined in the file. -func getSortedHosts(root *toml.Tree) ([]string, error) { - iter, ok := root.Get("host").(*toml.Tree) - if !ok { - return nil, errors.New("invalid `host` tree") +// getSortedHosts returns the list of hosts in the order are they defined in the file. +func getSortedHosts(b []byte) ([]string, error) { + var hostsInOrder []string + + // Use toml unstable package for directly parsing toml + // See https://github.com/pelletier/go-toml/discussions/801#discussioncomment-7083586 + p := tomlu.Parser{} + p.Reset(b) + + var host string + // iterate over all top level expressions + for p.NextExpression() { + e := p.Expression() + + if e.Kind != tomlu.Table { + continue + } + + // Let's look at the key. It's an iterator over the multiple dotted parts of the key. + var parts []string + for it := e.Key(); it.Next(); { + parts = append(parts, string(it.Node().Data)) + } + + // only consider keys that look like `hosts.XXX` + // and skip subtables such as `hosts.XXX.header` + if len(parts) < 2 || parts[0] != "host" || parts[1] == host { + continue + } + + host = parts[1] + hostsInOrder = append(hostsInOrder, host) } - list := append([]string{}, iter.Keys()...) - - // go-toml stores TOML sections in the map object, so no order guaranteed. - // We retrieve line number for each key and sort the keys by position. - sort.Slice(list, func(i, j int) bool { - h1 := iter.GetPath([]string{list[i]}).(*toml.Tree) - h2 := iter.GetPath([]string{list[j]}).(*toml.Tree) - return h1.Position().Line < h2.Position().Line - }) - - return list, nil + return hostsInOrder, nil } // makeStringSlice is a helper func to convert from []interface{} to []string. diff --git a/vendor/github.com/containerd/containerd/remotes/docker/converter.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/converter.go similarity index 91% rename from vendor/github.com/containerd/containerd/remotes/docker/converter.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/converter.go index 95a68d70e6..f21103e17f 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/converter.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/converter.go @@ -22,9 +22,9 @@ import ( "encoding/json" "fmt" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" "github.com/containerd/log" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -41,9 +41,7 @@ const LegacyConfigMediaType = "application/octet-stream" // 1. original manifest will be deleted by next gc round. // 2. don't cover manifest list. func ConvertManifest(ctx context.Context, store content.Store, desc ocispec.Descriptor) (ocispec.Descriptor, error) { - if !(desc.MediaType == images.MediaTypeDockerSchema2Manifest || - desc.MediaType == ocispec.MediaTypeImageManifest) { - + if !images.IsManifestType(desc.MediaType) { log.G(ctx).Warnf("do nothing for media type: %s", desc.MediaType) return desc, nil } diff --git a/vendor/github.com/containerd/containerd/remotes/docker/converter_fuzz.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/converter_fuzz.go similarity index 90% rename from vendor/github.com/containerd/containerd/remotes/docker/converter_fuzz.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/converter_fuzz.go index aa7cf4666f..c97b6b8994 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/converter_fuzz.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/converter_fuzz.go @@ -23,10 +23,9 @@ import ( "os" fuzz "github.com/AdaLogics/go-fuzz-headers" - "github.com/containerd/containerd/content/local" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/containerd/log" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/sirupsen/logrus" ) func FuzzConvertManifest(data []byte) int { @@ -34,7 +33,7 @@ func FuzzConvertManifest(data []byte) int { // Do not log the message below // level=warning msg="do nothing for media type: ..." - log.G(ctx).Logger.SetLevel(logrus.PanicLevel) + log.G(ctx).Logger.SetLevel(log.PanicLevel) f := fuzz.NewConsumer(data) desc := ocispec.Descriptor{} diff --git a/vendor/github.com/containerd/containerd/remotes/docker/errcode.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/errcode.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/errcode.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/errcode.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/errdesc.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/errdesc.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/errdesc.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/errdesc.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/fetcher.go similarity index 80% rename from vendor/github.com/containerd/containerd/remotes/docker/fetcher.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/fetcher.go index c4c401ad1d..2c7d880a9d 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/fetcher.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/fetcher.go @@ -17,6 +17,8 @@ package docker import ( + "compress/flate" + "compress/gzip" "context" "encoding/json" "errors" @@ -26,12 +28,13 @@ import ( "net/url" "strings" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/klauspost/compress/zstd" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" ) type dockerFetcher struct { @@ -94,10 +97,8 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R } // Try manifests endpoints for manifests types - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList, - images.MediaTypeDockerSchema1Manifest, - ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex: + if images.IsManifestType(desc.MediaType) || images.IsIndexType(desc.MediaType) || + desc.MediaType == images.MediaTypeDockerSchema1Manifest { var firstErr error for _, host := range r.hosts { @@ -152,12 +153,18 @@ func (r dockerFetcher) Fetch(ctx context.Context, desc ocispec.Descriptor) (io.R }) } -func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, ps ...string) (*request, int64, error) { +func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, mediatype string, ps ...string) (*request, int64, error) { headReq := r.request(host, http.MethodHead, ps...) if err := headReq.addNamespace(r.refspec.Hostname()); err != nil { return nil, 0, err } + if mediatype == "" { + headReq.header.Set("Accept", "*/*") + } else { + headReq.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", ")) + } + headResp, err := headReq.doWithRetries(ctx, nil) if err != nil { return nil, 0, err @@ -176,9 +183,15 @@ func (r dockerFetcher) createGetReq(ctx context.Context, host RegistryHost, ps . return getReq, headResp.ContentLength, nil } -func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error) { +func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest, opts ...remotes.FetchByDigestOpts) (io.ReadCloser, ocispec.Descriptor, error) { var desc ocispec.Descriptor ctx = log.WithLogger(ctx, log.G(ctx).WithField("digest", dgst)) + var config remotes.FetchByDigestConfig + for _, o := range opts { + if err := o(ctx, &config); err != nil { + return nil, desc, err + } + } hosts := r.filterHosts(HostCapabilityPull) if len(hosts) == 0 { @@ -197,7 +210,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i ) for _, host := range r.hosts { - getReq, sz, err = r.createGetReq(ctx, host, "blobs", dgst.String()) + getReq, sz, err = r.createGetReq(ctx, host, config.Mediatype, "blobs", dgst.String()) if err == nil { break } @@ -210,7 +223,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i if getReq == nil { // Fall back to the "manifests" endpoint for _, host := range r.hosts { - getReq, sz, err = r.createGetReq(ctx, host, "manifests", dgst.String()) + getReq, sz, err = r.createGetReq(ctx, host, config.Mediatype, "manifests", dgst.String()) if err == nil { break } @@ -232,7 +245,7 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i } seeker, err := newHTTPReadSeeker(sz, func(offset int64) (io.ReadCloser, error) { - return r.open(ctx, getReq, "", offset) + return r.open(ctx, getReq, config.Mediatype, offset) }) if err != nil { return nil, desc, err @@ -243,6 +256,9 @@ func (r dockerFetcher) FetchByDigest(ctx context.Context, dgst digest.Digest) (i Digest: dgst, Size: sz, } + if config.Mediatype != "" { + desc.MediaType = config.Mediatype + } return seeker, desc, nil } @@ -252,6 +268,7 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, } else { req.header.Set("Accept", strings.Join([]string{mediatype, `*/*`}, ", ")) } + req.header.Set("Accept-Encoding", "zstd;q=1.0, gzip;q=0.8, deflate;q=0.5") if offset > 0 { // Note: "Accept-Ranges: bytes" cannot be trusted as some endpoints @@ -310,5 +327,32 @@ func (r dockerFetcher) open(ctx context.Context, req *request, mediatype string, } } - return resp.Body, nil + body := resp.Body + encoding := strings.FieldsFunc(resp.Header.Get("Content-Encoding"), func(r rune) bool { + return r == ' ' || r == '\t' || r == ',' + }) + for i := len(encoding) - 1; i >= 0; i-- { + algorithm := strings.ToLower(encoding[i]) + switch algorithm { + case "zstd": + r, err := zstd.NewReader(body) + if err != nil { + return nil, err + } + body = r.IOReadCloser() + case "gzip": + body, err = gzip.NewReader(body) + if err != nil { + return nil, err + } + case "deflate": + body = flate.NewReader(body) + case "identity", "": + // no content-encoding applied, use raw body + default: + return nil, errors.New("unsupported Content-Encoding algorithm: " + algorithm) + } + } + + return body, nil } diff --git a/vendor/github.com/containerd/containerd/remotes/docker/fetcher_fuzz.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/fetcher_fuzz.go similarity index 95% rename from vendor/github.com/containerd/containerd/remotes/docker/fetcher_fuzz.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/fetcher_fuzz.go index f396a74f4f..5da9dca7a6 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/fetcher_fuzz.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/fetcher_fuzz.go @@ -25,6 +25,7 @@ import ( "net/http" "net/http/httptest" "net/url" + "strconv" ) func FuzzFetcher(data []byte) int { @@ -35,7 +36,7 @@ func FuzzFetcher(data []byte) int { s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) { rw.Header().Set("content-range", fmt.Sprintf("bytes %d-%d/%d", 0, dataLen-1, dataLen)) - rw.Header().Set("content-length", fmt.Sprintf("%d", dataLen)) + rw.Header().Set("content-length", strconv.Itoa(dataLen)) rw.Write(data) })) defer s.Close() diff --git a/vendor/github.com/containerd/containerd/remotes/docker/handler.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/handler.go similarity index 93% rename from vendor/github.com/containerd/containerd/remotes/docker/handler.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/handler.go index ccec490133..615869a224 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/handler.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/handler.go @@ -22,10 +22,10 @@ import ( "net/url" "strings" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/containerd/log" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -103,7 +103,7 @@ func appendDistributionSourceLabel(originLabel, repo string) string { } func distributionSourceLabelKey(source string) string { - return fmt.Sprintf("%s.%s", labels.LabelDistributionSource, source) + return labels.LabelDistributionSource + "." + source } // selectRepositoryMountCandidate will select the repo which has longest diff --git a/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/httpreadseeker.go similarity index 98% rename from vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/httpreadseeker.go index deb888cbc8..6739e7904e 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/httpreadseeker.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/httpreadseeker.go @@ -21,9 +21,8 @@ import ( "fmt" "io" + "github.com/containerd/errdefs" "github.com/containerd/log" - - "github.com/containerd/containerd/errdefs" ) const maxRetry = 3 diff --git a/vendor/github.com/containerd/containerd/remotes/docker/pusher.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/pusher.go similarity index 96% rename from vendor/github.com/containerd/containerd/remotes/docker/pusher.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/pusher.go index f97ab144e8..f994fff5a8 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/pusher.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/pusher.go @@ -28,15 +28,14 @@ import ( "sync" "time" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + remoteserrors "github.com/containerd/containerd/v2/core/remotes/errors" + "github.com/containerd/errdefs" "github.com/containerd/log" digest "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - remoteserrors "github.com/containerd/containerd/remotes/errors" ) type dockerPusher struct { @@ -104,12 +103,10 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str host = hosts[0] ) - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, images.MediaTypeDockerSchema2ManifestList, - ocispec.MediaTypeImageManifest, ocispec.MediaTypeImageIndex: + if images.IsManifestType(desc.MediaType) || images.IsIndexType(desc.MediaType) { isManifest = true existCheck = getManifestPath(p.object, desc.Digest) - default: + } else { existCheck = []string{"blobs", desc.Digest.String()} } @@ -143,9 +140,7 @@ func (p dockerPusher) push(ctx context.Context, desc ocispec.Descriptor, ref str Exists: true, }, Status: content.Status{ - Ref: ref, - Total: desc.Size, - Offset: desc.Size, + Ref: ref, // TODO: Set updated time? }, }) diff --git a/vendor/github.com/containerd/containerd/remotes/docker/registry.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/registry.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/registry.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/registry.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver.go similarity index 90% rename from vendor/github.com/containerd/containerd/remotes/docker/resolver.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver.go index 8ce4cccc01..dce391c54b 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/resolver.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver.go @@ -30,18 +30,18 @@ import ( "strings" "sync" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. - remoteerrors "github.com/containerd/containerd/remotes/errors" - "github.com/containerd/containerd/tracing" - "github.com/containerd/containerd/version" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker/schema1" //nolint:staticcheck // Ignore SA1019. Need to keep deprecated package for compatibility. + remoteerrors "github.com/containerd/containerd/v2/core/remotes/errors" + "github.com/containerd/containerd/v2/pkg/reference" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/containerd/v2/version" ) var ( @@ -245,10 +245,9 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp } var ( - firstErr error - paths [][]string - dgst = refspec.Digest() - caps = HostCapabilityPull + paths [][]string + dgst = refspec.Digest() + caps = HostCapabilityPull ) if dgst != "" { @@ -279,8 +278,23 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp return "", ocispec.Descriptor{}, err } + var ( + // firstErr is the most relevant error encountered during resolution. + // We use this to determine the error to return, making sure that the + // error created furthest through the resolution process is returned. + firstErr error + firstErrPriority int + ) + + nextHostOrFail := func(i int) string { + if i < len(hosts)-1 { + return "trying next host" + } + return "fetch failed" + } + for _, u := range paths { - for _, host := range hosts { + for i, host := range hosts { ctx := log.WithLogger(ctx, log.G(ctx).WithField("host", host.Host)) req := base.request(host, http.MethodHead, u...) @@ -298,25 +312,30 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp if errors.Is(err, ErrInvalidAuthorization) { err = fmt.Errorf("pull access denied, repository does not exist or may require authorization: %w", err) } - // Store the error for referencing later - if firstErr == nil { + if firstErrPriority < 1 { firstErr = err + firstErrPriority = 1 } - log.G(ctx).WithError(err).Info("trying next host") + log.G(ctx).WithError(err).Info(nextHostOrFail(i)) continue // try another host } resp.Body.Close() // don't care about body contents. if resp.StatusCode > 299 { if resp.StatusCode == http.StatusNotFound { - log.G(ctx).Info("trying next host - response was http.StatusNotFound") + if firstErrPriority < 2 { + firstErr = fmt.Errorf("%s: %w", ref, errdefs.ErrNotFound) + firstErrPriority = 2 + } + log.G(ctx).Infof("%s after status: %s", nextHostOrFail(i), resp.Status) continue } if resp.StatusCode > 399 { - // Set firstErr when encountering the first non-404 status code. - if firstErr == nil { + if firstErrPriority < 3 { firstErr = remoteerrors.NewUnexpectedStatusErr(resp) + firstErrPriority = 3 } + log.G(ctx).Infof("%s after status: %s", nextHostOrFail(i), resp.Status) continue // try another host } return "", ocispec.Descriptor{}, remoteerrors.NewUnexpectedStatusErr(resp) @@ -387,8 +406,9 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp } // Prevent resolving to excessively large manifests if size > MaxManifestSize { - if firstErr == nil { + if firstErrPriority < 4 { firstErr = fmt.Errorf("rejecting %d byte manifest for %s: %w", size, ref, errdefs.ErrNotFound) + firstErrPriority = 4 } continue } @@ -404,10 +424,8 @@ func (r *dockerResolver) Resolve(ctx context.Context, ref string) (string, ocisp } } - // If above loop terminates without return, then there was an error. - // "firstErr" contains the first non-404 error. That is, "firstErr == nil" - // means that either no registries were given or each registry returned 404. - + // If above loop terminates without return or error, then no registries + // were provided. if firstErr == nil { firstErr = fmt.Errorf("%s: %w", ref, errdefs.ErrNotFound) } @@ -787,37 +805,3 @@ func isPortError(err error, host string) bool { return false } - -// HTTPFallback is an http.RoundTripper which allows fallback from https to http -// for registry endpoints with configurations for both http and TLS, such as -// defaulted localhost endpoints. -// -// Deprecated: Use NewHTTPFallback instead. -type HTTPFallback struct { - http.RoundTripper -} - -func (f HTTPFallback) RoundTrip(r *http.Request) (*http.Response, error) { - resp, err := f.RoundTripper.RoundTrip(r) - var tlsErr tls.RecordHeaderError - if errors.As(err, &tlsErr) && string(tlsErr.RecordHeader[:]) == "HTTP/" { - // server gave HTTP response to HTTPS client - plainHTTPUrl := *r.URL - plainHTTPUrl.Scheme = "http" - - plainHTTPRequest := *r - plainHTTPRequest.URL = &plainHTTPUrl - - if r.Body != nil && r.GetBody != nil { - body, err := r.GetBody() - if err != nil { - return nil, err - } - plainHTTPRequest.Body = body - } - - return f.RoundTripper.RoundTrip(&plainHTTPRequest) - } - - return resp, err -} diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver_unix.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/resolver_unix.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver_unix.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/resolver_windows.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/docker/resolver_windows.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/resolver_windows.go diff --git a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/schema1/converter.go similarity index 94% rename from vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/schema1/converter.go index b38c738552..e724e4e55a 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/schema1/converter.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/schema1/converter.go @@ -27,23 +27,24 @@ import ( "errors" "fmt" "io" + "os" "strconv" "strings" "sync" "time" + "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/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/deprecation" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/errdefs" "github.com/containerd/log" digest "github.com/opencontainers/go-digest" specs "github.com/opencontainers/image-spec/specs-go" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/errgroup" - - "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/labels" - "github.com/containerd/containerd/remotes" ) const ( @@ -68,14 +69,30 @@ type Converter struct { layerBlobs map[digest.Digest]ocispec.Descriptor } +var ErrDisabled = fmt.Errorf("Pulling Schema 1 images have been deprecated and disabled by default since containerd v2.0. "+ + "As a workaround you may set an environment variable `%s=1`, but this will be completely removed in containerd v2.1.", + deprecation.EnvPullSchema1Image) + // NewConverter returns a new converter -func NewConverter(contentStore content.Store, fetcher remotes.Fetcher) *Converter { +func NewConverter(contentStore content.Store, fetcher remotes.Fetcher) (*Converter, error) { + s := os.Getenv(deprecation.EnvPullSchema1Image) + if s == "" { + return nil, ErrDisabled + } + enable, err := strconv.ParseBool(s) + if err != nil { + return nil, fmt.Errorf("failed to parse `%s=%s`: %w", deprecation.EnvPullSchema1Image, s, err) + } + if !enable { + return nil, ErrDisabled + } + log.L.Warn(ErrDisabled) return &Converter{ contentStore: contentStore, fetcher: fetcher, blobMap: map[digest.Digest]blobState{}, layerBlobs: map[digest.Digest]ocispec.Descriptor{}, - } + }, nil } // Handle fetching descriptors for a docker media type diff --git a/vendor/github.com/containerd/containerd/remotes/docker/scope.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/scope.go similarity index 98% rename from vendor/github.com/containerd/containerd/remotes/docker/scope.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/scope.go index 95b4810ab9..8135498bd9 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/scope.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/scope.go @@ -23,7 +23,7 @@ import ( "sort" "strings" - "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/v2/pkg/reference" ) // RepositoryScope returns a repository scope string such as "repository:foo/bar:pull" diff --git a/vendor/github.com/containerd/containerd/remotes/docker/status.go b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/status.go similarity index 96% rename from vendor/github.com/containerd/containerd/remotes/docker/status.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/docker/status.go index 1a9227725b..9835525ab5 100644 --- a/vendor/github.com/containerd/containerd/remotes/docker/status.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/docker/status.go @@ -20,8 +20,8 @@ import ( "fmt" "sync" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/errdefs" "github.com/moby/locker" ) diff --git a/vendor/github.com/containerd/containerd/remotes/errors/errors.go b/vendor/github.com/containerd/containerd/v2/core/remotes/errors/errors.go similarity index 100% rename from vendor/github.com/containerd/containerd/remotes/errors/errors.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/errors/errors.go diff --git a/vendor/github.com/containerd/containerd/remotes/handlers.go b/vendor/github.com/containerd/containerd/v2/core/remotes/handlers.go similarity index 86% rename from vendor/github.com/containerd/containerd/remotes/handlers.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/handlers.go index 365ff5fc00..16fcdbf84d 100644 --- a/vendor/github.com/containerd/containerd/remotes/handlers.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/handlers.go @@ -25,15 +25,14 @@ import ( "strings" "sync" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/semaphore" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" ) type refKeyPrefix struct{} @@ -72,17 +71,17 @@ func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string { } } - switch mt := desc.MediaType; { - case mt == images.MediaTypeDockerSchema2Manifest || mt == ocispec.MediaTypeImageManifest: + switch { + case images.IsManifestType(desc.MediaType): return "manifest-" + key - case mt == images.MediaTypeDockerSchema2ManifestList || mt == ocispec.MediaTypeImageIndex: + case images.IsIndexType(desc.MediaType): return "index-" + key - case images.IsLayerType(mt): + case images.IsLayerType(desc.MediaType): return "layer-" + key - case images.IsKnownConfig(mt): + case images.IsKnownConfig(desc.MediaType): return "config-" + key default: - log.G(ctx).Warnf("reference for unknown type: %s", mt) + log.G(ctx).Warnf("reference for unknown type: %s", desc.MediaType) return "unknown-" + key } } @@ -91,23 +90,21 @@ func MakeRefKey(ctx context.Context, desc ocispec.Descriptor) string { // discovered in a call to Dispatch. Use with ChildrenHandler to do a full // recursive fetch. func FetchHandler(ingester content.Ingester, fetcher Fetcher) images.HandlerFunc { - return func(ctx context.Context, desc ocispec.Descriptor) (subdescs []ocispec.Descriptor, err error) { + return func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { ctx = log.WithLogger(ctx, log.G(ctx).WithFields(log.Fields{ "digest": desc.Digest, "mediatype": desc.MediaType, "size": desc.Size, })) - switch desc.MediaType { - case images.MediaTypeDockerSchema1Manifest: + if desc.MediaType == images.MediaTypeDockerSchema1Manifest { return nil, fmt.Errorf("%v not supported", desc.MediaType) - default: - err := Fetch(ctx, ingester, fetcher, desc) - if errdefs.IsAlreadyExists(err) { - return nil, nil - } - return nil, err } + err := Fetch(ctx, ingester, fetcher, desc) + if errdefs.IsAlreadyExists(err) { + return nil, nil + } + return nil, err } } @@ -215,20 +212,18 @@ func PushContent(ctx context.Context, pusher Pusher, desc ocispec.Descriptor, st indexStack := []ocispec.Descriptor{} filterHandler := images.HandlerFunc(func(ctx context.Context, desc ocispec.Descriptor) ([]ocispec.Descriptor, error) { - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: + if images.IsManifestType(desc.MediaType) { m.Lock() manifests = append(manifests, desc) m.Unlock() return nil, images.ErrStopHandler - case images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: + } else if images.IsIndexType(desc.MediaType) { m.Lock() indexStack = append(indexStack, desc) m.Unlock() return nil, images.ErrStopHandler - default: - return nil, nil } + return nil, nil }) pushHandler := PushHandler(pusher, store) @@ -285,10 +280,6 @@ func SkipNonDistributableBlobs(f images.HandlerFunc) images.HandlerFunc { return nil, images.ErrSkipDesc } - if images.IsLayerType(desc.MediaType) { - return nil, nil - } - children, err := f(ctx, desc) if err != nil { return nil, err @@ -323,24 +314,16 @@ func FilterManifestByPlatformHandler(f images.HandlerFunc, m platforms.Matcher) return children, nil } - var descs []ocispec.Descriptor - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: - if m.Match(*desc.Platform) { - descs = children - } else { - for _, child := range children { - if child.MediaType == images.MediaTypeDockerSchema2Config || - child.MediaType == ocispec.MediaTypeImageConfig { - - descs = append(descs, child) - } + if images.IsManifestType(desc.MediaType) && !m.Match(*desc.Platform) { + var descs []ocispec.Descriptor + for _, child := range children { + if images.IsConfigType(child.MediaType) { + descs = append(descs, child) } } - default: - descs = children + return descs, nil } - return descs, nil + return children, nil } } @@ -355,10 +338,7 @@ func annotateDistributionSourceHandler(f images.HandlerFunc, provider content.In // Distribution source is only used for config or blob but may be inherited from // a manifest or manifest list - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest, - images.MediaTypeDockerSchema2ManifestList, ocispec.MediaTypeImageIndex: - default: + if !images.IsManifestType(desc.MediaType) && !images.IsIndexType(desc.MediaType) { return children, nil } diff --git a/vendor/github.com/containerd/containerd/remotes/resolver.go b/vendor/github.com/containerd/containerd/v2/core/remotes/resolver.go similarity index 81% rename from vendor/github.com/containerd/containerd/remotes/resolver.go rename to vendor/github.com/containerd/containerd/v2/core/remotes/resolver.go index f200c84bc7..c39b93785e 100644 --- a/vendor/github.com/containerd/containerd/remotes/resolver.go +++ b/vendor/github.com/containerd/containerd/v2/core/remotes/resolver.go @@ -20,7 +20,7 @@ import ( "context" "io" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -65,7 +65,7 @@ type FetcherByDigest interface { // FetcherByDigest usually returns an incomplete descriptor. // Typically, the media type is always set to "application/octet-stream", // and the annotations are unset. - FetchByDigest(ctx context.Context, dgst digest.Digest) (io.ReadCloser, ocispec.Descriptor, error) + FetchByDigest(ctx context.Context, dgst digest.Digest, opts ...FetchByDigestOpts) (io.ReadCloser, ocispec.Descriptor, error) } // Pusher pushes content @@ -92,3 +92,20 @@ type PusherFunc func(ctx context.Context, desc ocispec.Descriptor) (content.Writ func (fn PusherFunc) Push(ctx context.Context, desc ocispec.Descriptor) (content.Writer, error) { return fn(ctx, desc) } + +// FetchByDigestConfig provides configuration for fetching content by digest +type FetchByDigestConfig struct { + //Mediatype specifies mediatype header to append for fetch request + Mediatype string +} + +// FetchByDigestOpts allows callers to set options for fetch object +type FetchByDigestOpts func(context.Context, *FetchByDigestConfig) error + +// WithMediaType sets the media type header for fetch request +func WithMediaType(mediatype string) FetchByDigestOpts { + return func(ctx context.Context, cfg *FetchByDigestConfig) error { + cfg.Mediatype = mediatype + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/sandbox/bridge.go b/vendor/github.com/containerd/containerd/v2/core/sandbox/bridge.go similarity index 96% rename from vendor/github.com/containerd/containerd/sandbox/bridge.go rename to vendor/github.com/containerd/containerd/v2/core/sandbox/bridge.go index 3c1a9c2fd0..2c2749b00d 100644 --- a/vendor/github.com/containerd/containerd/sandbox/bridge.go +++ b/vendor/github.com/containerd/containerd/v2/core/sandbox/bridge.go @@ -24,7 +24,6 @@ import ( "google.golang.org/grpc" api "github.com/containerd/containerd/api/runtime/sandbox/v1" - "github.com/containerd/containerd/errdefs" ) // NewClient returns a new sandbox client that handles both GRPC and TTRPC clients. @@ -78,5 +77,5 @@ func (g *grpcBridge) ShutdownSandbox(ctx context.Context, request *api.ShutdownS } func (g *grpcBridge) SandboxMetrics(ctx context.Context, request *api.SandboxMetricsRequest) (*api.SandboxMetricsResponse, error) { - return nil, errdefs.ToGRPC(errdefs.ErrNotImplemented) + return g.client.SandboxMetrics(ctx, request) } diff --git a/vendor/github.com/containerd/containerd/sandbox/controller.go b/vendor/github.com/containerd/containerd/v2/core/sandbox/controller.go similarity index 79% rename from vendor/github.com/containerd/containerd/sandbox/controller.go rename to vendor/github.com/containerd/containerd/v2/core/sandbox/controller.go index 4885b43668..328f8399ac 100644 --- a/vendor/github.com/containerd/containerd/sandbox/controller.go +++ b/vendor/github.com/containerd/containerd/v2/core/sandbox/controller.go @@ -22,25 +22,26 @@ import ( "time" "github.com/containerd/containerd/api/types" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/typeurl/v2" imagespec "github.com/opencontainers/image-spec/specs-go/v1" ) type CreateOptions struct { - Rootfs []*types.Mount + Rootfs []mount.Mount // Options are used to pass arbitrary options to the shim when creating a new sandbox. // CRI will use this to pass PodSandboxConfig. // Don't confuse this with Runtime options, which are passed at shim instance start // to setup global shim configuration. - Options typeurl.Any - NetNSPath string + Options typeurl.Any + NetNSPath string + Annotations map[string]string } type CreateOpt func(*CreateOptions) error // WithRootFS is used to create a sandbox with the provided rootfs mount -// TODO: Switch to mount.Mount once target added -func WithRootFS(m []*types.Mount) CreateOpt { +func WithRootFS(m []mount.Mount) CreateOpt { return func(co *CreateOptions) error { co.Rootfs = m return nil @@ -68,6 +69,14 @@ func WithNetNSPath(netNSPath string) CreateOpt { } } +// WithAnnotations sets the provided annotations for sandbox creation. +func WithAnnotations(annotations map[string]string) CreateOpt { + return func(co *CreateOptions) error { + co.Annotations = annotations + return nil + } +} + type StopOptions struct { Timeout *time.Duration } @@ -85,7 +94,7 @@ func WithTimeout(timeout time.Duration) StopOpt { // Shim lifetimes are now managed manually via sandbox API by the containerd's client. type Controller interface { // Create is used to initialize sandbox environment. (mounts, any) - Create(ctx context.Context, sandboxID string, opts ...CreateOpt) error + Create(ctx context.Context, sandboxInfo Sandbox, opts ...CreateOpt) error // Start will start previously created sandbox. Start(ctx context.Context, sandboxID string) (ControllerInstance, error) // Platform returns target sandbox OS that will be used by Controller. @@ -100,12 +109,19 @@ type Controller interface { Status(ctx context.Context, sandboxID string, verbose bool) (ControllerStatus, error) // Shutdown deletes and cleans all tasks and sandbox instance. Shutdown(ctx context.Context, sandboxID string) error + // Metrics queries the sandbox for metrics. + Metrics(ctx context.Context, sandboxID string) (*types.Metric, error) + // Update changes a part of sandbox, such as extensions/annotations/labels/spec of + // Sandbox object, controllers may have to update the running sandbox according to the changes. + Update(ctx context.Context, sandboxID string, sandbox Sandbox, fields ...string) error } type ControllerInstance struct { SandboxID string Pid uint32 CreatedAt time.Time + Address string + Version uint32 Labels map[string]string } @@ -122,4 +138,6 @@ type ControllerStatus struct { CreatedAt time.Time ExitedAt time.Time Extra typeurl.Any + Address string + Version uint32 } diff --git a/vendor/github.com/containerd/containerd/sandbox/helpers.go b/vendor/github.com/containerd/containerd/v2/core/sandbox/helpers.go similarity index 84% rename from vendor/github.com/containerd/containerd/sandbox/helpers.go rename to vendor/github.com/containerd/containerd/v2/core/sandbox/helpers.go index bfe0b23d33..86e6fa1130 100644 --- a/vendor/github.com/containerd/containerd/sandbox/helpers.go +++ b/vendor/github.com/containerd/containerd/v2/core/sandbox/helpers.go @@ -18,8 +18,8 @@ package sandbox import ( "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/protobuf" - gogo_types "github.com/containerd/containerd/protobuf/types" + "github.com/containerd/containerd/v2/pkg/protobuf" + gogo_types "github.com/containerd/containerd/v2/pkg/protobuf/types" "github.com/containerd/typeurl/v2" ) @@ -27,19 +27,20 @@ import ( func ToProto(sandbox *Sandbox) *types.Sandbox { extensions := make(map[string]*gogo_types.Any) for k, v := range sandbox.Extensions { - extensions[k] = protobuf.FromAny(v) + extensions[k] = typeurl.MarshalProto(v) } return &types.Sandbox{ SandboxID: sandbox.ID, Runtime: &types.Sandbox_Runtime{ Name: sandbox.Runtime.Name, - Options: protobuf.FromAny(sandbox.Runtime.Options), + Options: typeurl.MarshalProto(sandbox.Runtime.Options), }, + Sandboxer: sandbox.Sandboxer, Labels: sandbox.Labels, CreatedAt: protobuf.ToTimestamp(sandbox.CreatedAt), UpdatedAt: protobuf.ToTimestamp(sandbox.UpdatedAt), Extensions: extensions, - Spec: protobuf.FromAny(sandbox.Spec), + Spec: typeurl.MarshalProto(sandbox.Spec), } } @@ -61,6 +62,7 @@ func FromProto(sandboxpb *types.Sandbox) Sandbox { Labels: sandboxpb.Labels, Runtime: runtime, Spec: sandboxpb.Spec, + Sandboxer: sandboxpb.Sandboxer, CreatedAt: protobuf.FromTimestamp(sandboxpb.CreatedAt), UpdatedAt: protobuf.FromTimestamp(sandboxpb.UpdatedAt), Extensions: extensions, diff --git a/vendor/github.com/containerd/containerd/sandbox/proxy/controller.go b/vendor/github.com/containerd/containerd/v2/core/sandbox/proxy/controller.go similarity index 51% rename from vendor/github.com/containerd/containerd/sandbox/proxy/controller.go rename to vendor/github.com/containerd/containerd/v2/core/sandbox/proxy/controller.go index a18f3e6acf..121785f618 100644 --- a/vendor/github.com/containerd/containerd/sandbox/proxy/controller.go +++ b/vendor/github.com/containerd/containerd/v2/core/sandbox/proxy/controller.go @@ -18,52 +18,61 @@ package proxy import ( "context" - - imagespec "github.com/opencontainers/image-spec/specs-go/v1" - "google.golang.org/protobuf/types/known/anypb" + "time" api "github.com/containerd/containerd/api/services/sandbox/v1" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/sandbox" + "github.com/containerd/containerd/api/types" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/typeurl/v2" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" + + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/sandbox" ) // remoteSandboxController is a low level GRPC client for containerd's sandbox controller service type remoteSandboxController struct { - client api.ControllerClient + client api.ControllerClient + sandboxerName string } var _ sandbox.Controller = (*remoteSandboxController)(nil) // NewSandboxController creates a client for a sandbox controller -func NewSandboxController(client api.ControllerClient) sandbox.Controller { - return &remoteSandboxController{client: client} +func NewSandboxController(client api.ControllerClient, name string) sandbox.Controller { + return &remoteSandboxController{client: client, sandboxerName: name} } -func (s *remoteSandboxController) Create(ctx context.Context, sandboxID string, opts ...sandbox.CreateOpt) error { +func (s *remoteSandboxController) Create(ctx context.Context, sandboxInfo sandbox.Sandbox, opts ...sandbox.CreateOpt) error { var options sandbox.CreateOptions for _, opt := range opts { opt(&options) } + apiSandbox := sandbox.ToProto(&sandboxInfo) _, err := s.client.Create(ctx, &api.ControllerCreateRequest{ - SandboxID: sandboxID, - Rootfs: options.Rootfs, - Options: &anypb.Any{ - TypeUrl: options.Options.GetTypeUrl(), - Value: options.Options.GetValue(), - }, - NetnsPath: options.NetNSPath, + SandboxID: sandboxInfo.ID, + Rootfs: mount.ToProto(options.Rootfs), + Options: typeurl.MarshalProto(options.Options), + NetnsPath: options.NetNSPath, + Annotations: options.Annotations, + Sandbox: apiSandbox, + Sandboxer: s.sandboxerName, }) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } func (s *remoteSandboxController) Start(ctx context.Context, sandboxID string) (sandbox.ControllerInstance, error) { - resp, err := s.client.Start(ctx, &api.ControllerStartRequest{SandboxID: sandboxID}) + resp, err := s.client.Start(ctx, &api.ControllerStartRequest{ + SandboxID: sandboxID, + Sandboxer: s.sandboxerName, + }) if err != nil { - return sandbox.ControllerInstance{}, errdefs.FromGRPC(err) + return sandbox.ControllerInstance{}, errgrpc.ToNative(err) } return sandbox.ControllerInstance{ @@ -71,13 +80,18 @@ func (s *remoteSandboxController) Start(ctx context.Context, sandboxID string) ( Pid: resp.GetPid(), CreatedAt: resp.GetCreatedAt().AsTime(), Labels: resp.GetLabels(), + Address: resp.GetAddress(), + Version: resp.GetVersion(), }, nil } func (s *remoteSandboxController) Platform(ctx context.Context, sandboxID string) (imagespec.Platform, error) { - resp, err := s.client.Platform(ctx, &api.ControllerPlatformRequest{SandboxID: sandboxID}) + resp, err := s.client.Platform(ctx, &api.ControllerPlatformRequest{ + SandboxID: sandboxID, + Sandboxer: s.sandboxerName, + }) if err != nil { - return imagespec.Platform{}, errdefs.FromGRPC(err) + return imagespec.Platform{}, errgrpc.ToNative(err) } platform := resp.GetPlatform() @@ -93,31 +107,62 @@ func (s *remoteSandboxController) Stop(ctx context.Context, sandboxID string, op for _, opt := range opts { opt(&soptions) } - req := &api.ControllerStopRequest{SandboxID: sandboxID} + req := &api.ControllerStopRequest{ + SandboxID: sandboxID, + Sandboxer: s.sandboxerName, + } if soptions.Timeout != nil { req.TimeoutSecs = uint32(soptions.Timeout.Seconds()) } _, err := s.client.Stop(ctx, req) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } func (s *remoteSandboxController) Shutdown(ctx context.Context, sandboxID string) error { - _, err := s.client.Shutdown(ctx, &api.ControllerShutdownRequest{SandboxID: sandboxID}) + _, err := s.client.Shutdown(ctx, &api.ControllerShutdownRequest{ + SandboxID: sandboxID, + Sandboxer: s.sandboxerName, + }) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } return nil } func (s *remoteSandboxController) Wait(ctx context.Context, sandboxID string) (sandbox.ExitStatus, error) { - resp, err := s.client.Wait(ctx, &api.ControllerWaitRequest{SandboxID: sandboxID}) - if err != nil { - return sandbox.ExitStatus{}, errdefs.FromGRPC(err) + // For remote sandbox controllers, the controller process may restart, + // we have to retry if the error indicates that it is the grpc disconnection. + var ( + resp *api.ControllerWaitResponse + err error + retryInterval time.Duration = 128 + ) + for { + resp, err = s.client.Wait(ctx, &api.ControllerWaitRequest{ + SandboxID: sandboxID, + Sandboxer: s.sandboxerName, + }) + if err != nil { + grpcErr := errgrpc.ToNative(err) + if !errdefs.IsUnavailable(grpcErr) { + return sandbox.ExitStatus{}, grpcErr + } + select { + case <-time.After(retryInterval * time.Millisecond): + if retryInterval < 4096 { + retryInterval = retryInterval << 1 + } + continue + case <-ctx.Done(): + return sandbox.ExitStatus{}, grpcErr + } + } + break } return sandbox.ExitStatus{ @@ -127,9 +172,13 @@ func (s *remoteSandboxController) Wait(ctx context.Context, sandboxID string) (s } func (s *remoteSandboxController) Status(ctx context.Context, sandboxID string, verbose bool) (sandbox.ControllerStatus, error) { - resp, err := s.client.Status(ctx, &api.ControllerStatusRequest{SandboxID: sandboxID, Verbose: verbose}) + resp, err := s.client.Status(ctx, &api.ControllerStatusRequest{ + SandboxID: sandboxID, + Verbose: verbose, + Sandboxer: s.sandboxerName, + }) if err != nil { - return sandbox.ControllerStatus{}, errdefs.FromGRPC(err) + return sandbox.ControllerStatus{}, errgrpc.ToNative(err) } return sandbox.ControllerStatus{ SandboxID: sandboxID, @@ -139,5 +188,35 @@ func (s *remoteSandboxController) Status(ctx context.Context, sandboxID string, CreatedAt: resp.GetCreatedAt().AsTime(), ExitedAt: resp.GetExitedAt().AsTime(), Extra: resp.GetExtra(), + Address: resp.GetAddress(), + Version: resp.GetVersion(), }, nil } + +func (s *remoteSandboxController) Metrics(ctx context.Context, sandboxID string) (*types.Metric, error) { + resp, err := s.client.Metrics(ctx, &api.ControllerMetricsRequest{ + SandboxID: sandboxID, + Sandboxer: s.sandboxerName, + }) + if err != nil { + return nil, errgrpc.ToNative(err) + } + return resp.Metrics, nil +} + +func (s *remoteSandboxController) Update( + ctx context.Context, + sandboxID string, + sb sandbox.Sandbox, + fields ...string) error { + apiSandbox := sandbox.ToProto(&sb) + _, err := s.client.Update(ctx, &api.ControllerUpdateRequest{ + SandboxID: sandboxID, + Sandbox: apiSandbox, + Fields: fields, + }) + if err != nil { + return errgrpc.ToNative(err) + } + return nil +} diff --git a/vendor/github.com/containerd/containerd/sandbox/proxy/store.go b/vendor/github.com/containerd/containerd/v2/core/sandbox/proxy/store.go similarity index 88% rename from vendor/github.com/containerd/containerd/sandbox/proxy/store.go rename to vendor/github.com/containerd/containerd/v2/core/sandbox/proxy/store.go index 64e4a2b320..09fdce1087 100644 --- a/vendor/github.com/containerd/containerd/sandbox/proxy/store.go +++ b/vendor/github.com/containerd/containerd/v2/core/sandbox/proxy/store.go @@ -20,8 +20,9 @@ import ( "context" api "github.com/containerd/containerd/api/services/sandbox/v1" - "github.com/containerd/containerd/errdefs" - sb "github.com/containerd/containerd/sandbox" + "github.com/containerd/errdefs/pkg/errgrpc" + + sb "github.com/containerd/containerd/v2/core/sandbox" ) // remoteSandboxStore is a low-level containerd client to manage sandbox environments metadata @@ -41,7 +42,7 @@ func (s *remoteSandboxStore) Create(ctx context.Context, sandbox sb.Sandbox) (sb Sandbox: sb.ToProto(&sandbox), }) if err != nil { - return sb.Sandbox{}, errdefs.FromGRPC(err) + return sb.Sandbox{}, errgrpc.ToNative(err) } return sb.FromProto(resp.Sandbox), nil @@ -53,7 +54,7 @@ func (s *remoteSandboxStore) Update(ctx context.Context, sandbox sb.Sandbox, fie Fields: fieldpaths, }) if err != nil { - return sb.Sandbox{}, errdefs.FromGRPC(err) + return sb.Sandbox{}, errgrpc.ToNative(err) } return sb.FromProto(resp.Sandbox), nil @@ -64,7 +65,7 @@ func (s *remoteSandboxStore) Get(ctx context.Context, id string) (sb.Sandbox, er SandboxID: id, }) if err != nil { - return sb.Sandbox{}, errdefs.FromGRPC(err) + return sb.Sandbox{}, errgrpc.ToNative(err) } return sb.FromProto(resp.Sandbox), nil @@ -75,7 +76,7 @@ func (s *remoteSandboxStore) List(ctx context.Context, filters ...string) ([]sb. Filters: filters, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } out := make([]sb.Sandbox, len(resp.List)) @@ -91,5 +92,5 @@ func (s *remoteSandboxStore) Delete(ctx context.Context, id string) error { SandboxID: id, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } diff --git a/vendor/github.com/containerd/containerd/sandbox/store.go b/vendor/github.com/containerd/containerd/v2/core/sandbox/store.go similarity index 96% rename from vendor/github.com/containerd/containerd/sandbox/store.go rename to vendor/github.com/containerd/containerd/v2/core/sandbox/store.go index cda646dde2..705e86faca 100644 --- a/vendor/github.com/containerd/containerd/sandbox/store.go +++ b/vendor/github.com/containerd/containerd/v2/core/sandbox/store.go @@ -21,7 +21,7 @@ import ( "fmt" "time" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" "github.com/containerd/typeurl/v2" ) @@ -35,6 +35,8 @@ type Sandbox struct { Runtime RuntimeOpts // Spec carries the runtime specification used to implement the sandbox Spec typeurl.Any + // Sandboxer is the sandbox controller who manages the sandbox + Sandboxer string // CreatedAt is the time at which the sandbox was created CreatedAt time.Time // UpdatedAt is the time at which the sandbox was updated diff --git a/vendor/github.com/containerd/containerd/v2/core/snapshots/proxy/convert.go b/vendor/github.com/containerd/containerd/v2/core/snapshots/proxy/convert.go new file mode 100644 index 0000000000..b987be0abe --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/snapshots/proxy/convert.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 proxy + +import ( + snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/protobuf" +) + +// KindToProto converts from [Kind] to the protobuf definition [snapshots.Kind]. +func KindToProto(kind snapshots.Kind) snapshotsapi.Kind { + switch kind { + case snapshots.KindActive: + return snapshotsapi.Kind_ACTIVE + case snapshots.KindView: + return snapshotsapi.Kind_VIEW + default: + return snapshotsapi.Kind_COMMITTED + } +} + +// KindFromProto converts from the protobuf definition [snapshots.Kind] to +// [Kind]. +func KindFromProto(kind snapshotsapi.Kind) snapshots.Kind { + switch kind { + case snapshotsapi.Kind_ACTIVE: + return snapshots.KindActive + case snapshotsapi.Kind_VIEW: + return snapshots.KindView + default: + return snapshots.KindCommitted + } +} + +// InfoToProto converts from [Info] to the protobuf definition [snapshots.Info]. +func InfoToProto(info snapshots.Info) *snapshotsapi.Info { + return &snapshotsapi.Info{ + Name: info.Name, + Parent: info.Parent, + Kind: KindToProto(info.Kind), + CreatedAt: protobuf.ToTimestamp(info.Created), + UpdatedAt: protobuf.ToTimestamp(info.Updated), + Labels: info.Labels, + } +} + +// InfoFromProto converts from the protobuf definition [snapshots.Info] to +// [Info]. +func InfoFromProto(info *snapshotsapi.Info) snapshots.Info { + return snapshots.Info{ + Name: info.Name, + Parent: info.Parent, + Kind: KindFromProto(info.Kind), + Created: protobuf.FromTimestamp(info.CreatedAt), + Updated: protobuf.FromTimestamp(info.UpdatedAt), + Labels: info.Labels, + } +} + +// UsageFromProto converts from the protobuf definition [snapshots.Usage] to +// [Usage]. +func UsageFromProto(resp *snapshotsapi.UsageResponse) snapshots.Usage { + return snapshots.Usage{ + Inodes: resp.Inodes, + Size: resp.Size, + } +} + +// UsageToProto converts from [Usage] to the protobuf definition [snapshots.Usage]. +func UsageToProto(usage snapshots.Usage) *snapshotsapi.UsageResponse { + return &snapshotsapi.UsageResponse{ + Inodes: usage.Inodes, + Size: usage.Size, + } +} diff --git a/vendor/github.com/containerd/containerd/snapshots/proxy/proxy.go b/vendor/github.com/containerd/containerd/v2/core/snapshots/proxy/proxy.go similarity index 64% rename from vendor/github.com/containerd/containerd/snapshots/proxy/proxy.go rename to vendor/github.com/containerd/containerd/v2/core/snapshots/proxy/proxy.go index 3ef3b2698e..3e4aef983d 100644 --- a/vendor/github.com/containerd/containerd/snapshots/proxy/proxy.go +++ b/vendor/github.com/containerd/containerd/v2/core/snapshots/proxy/proxy.go @@ -21,12 +21,11 @@ import ( "io" snapshotsapi "github.com/containerd/containerd/api/services/snapshots/v1" - "github.com/containerd/containerd/api/types" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/protobuf" - protobuftypes "github.com/containerd/containerd/protobuf/types" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/errdefs/pkg/errgrpc" + + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + protobuftypes "github.com/containerd/containerd/v2/pkg/protobuf/types" ) // NewSnapshotter returns a new Snapshotter which communicates over a GRPC @@ -50,24 +49,24 @@ func (p *proxySnapshotter) Stat(ctx context.Context, key string) (snapshots.Info Key: key, }) if err != nil { - return snapshots.Info{}, errdefs.FromGRPC(err) + return snapshots.Info{}, errgrpc.ToNative(err) } - return toInfo(resp.Info), nil + return InfoFromProto(resp.Info), nil } func (p *proxySnapshotter) Update(ctx context.Context, info snapshots.Info, fieldpaths ...string) (snapshots.Info, error) { resp, err := p.client.Update(ctx, &snapshotsapi.UpdateSnapshotRequest{ Snapshotter: p.snapshotterName, - Info: fromInfo(info), + Info: InfoToProto(info), UpdateMask: &protobuftypes.FieldMask{ Paths: fieldpaths, }, }) if err != nil { - return snapshots.Info{}, errdefs.FromGRPC(err) + return snapshots.Info{}, errgrpc.ToNative(err) } - return toInfo(resp.Info), nil + return InfoFromProto(resp.Info), nil } func (p *proxySnapshotter) Usage(ctx context.Context, key string) (snapshots.Usage, error) { @@ -76,9 +75,9 @@ func (p *proxySnapshotter) Usage(ctx context.Context, key string) (snapshots.Usa Key: key, }) if err != nil { - return snapshots.Usage{}, errdefs.FromGRPC(err) + return snapshots.Usage{}, errgrpc.ToNative(err) } - return toUsage(resp), nil + return UsageFromProto(resp), nil } func (p *proxySnapshotter) Mounts(ctx context.Context, key string) ([]mount.Mount, error) { @@ -87,9 +86,9 @@ func (p *proxySnapshotter) Mounts(ctx context.Context, key string) ([]mount.Moun Key: key, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } - return toMounts(resp.Mounts), nil + return mount.FromProto(resp.Mounts), nil } func (p *proxySnapshotter) Prepare(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { @@ -106,9 +105,9 @@ func (p *proxySnapshotter) Prepare(ctx context.Context, key, parent string, opts Labels: local.Labels, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } - return toMounts(resp.Mounts), nil + return mount.FromProto(resp.Mounts), nil } func (p *proxySnapshotter) View(ctx context.Context, key, parent string, opts ...snapshots.Opt) ([]mount.Mount, error) { @@ -125,9 +124,9 @@ func (p *proxySnapshotter) View(ctx context.Context, key, parent string, opts .. Labels: local.Labels, }) if err != nil { - return nil, errdefs.FromGRPC(err) + return nil, errgrpc.ToNative(err) } - return toMounts(resp.Mounts), nil + return mount.FromProto(resp.Mounts), nil } func (p *proxySnapshotter) Commit(ctx context.Context, name, key string, opts ...snapshots.Opt) error { @@ -143,7 +142,7 @@ func (p *proxySnapshotter) Commit(ctx context.Context, name, key string, opts .. Key: key, Labels: local.Labels, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (p *proxySnapshotter) Remove(ctx context.Context, key string) error { @@ -151,7 +150,7 @@ func (p *proxySnapshotter) Remove(ctx context.Context, key string) error { Snapshotter: p.snapshotterName, Key: key, }) - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } func (p *proxySnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs ...string) error { @@ -160,7 +159,7 @@ func (p *proxySnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs . Filters: fs, }) if err != nil { - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } for { resp, err := sc.Recv() @@ -168,13 +167,13 @@ func (p *proxySnapshotter) Walk(ctx context.Context, fn snapshots.WalkFunc, fs . if err == io.EOF { return nil } - return errdefs.FromGRPC(err) + return errgrpc.ToNative(err) } if resp == nil { return nil } for _, info := range resp.Info { - if err := fn(ctx, toInfo(info)); err != nil { + if err := fn(ctx, InfoFromProto(info)); err != nil { return err } } @@ -189,67 +188,5 @@ func (p *proxySnapshotter) Cleanup(ctx context.Context) error { _, err := p.client.Cleanup(ctx, &snapshotsapi.CleanupRequest{ Snapshotter: p.snapshotterName, }) - return errdefs.FromGRPC(err) -} - -func toKind(kind snapshotsapi.Kind) snapshots.Kind { - if kind == snapshotsapi.Kind_ACTIVE { - return snapshots.KindActive - } - if kind == snapshotsapi.Kind_VIEW { - return snapshots.KindView - } - return snapshots.KindCommitted -} - -func toInfo(info *snapshotsapi.Info) snapshots.Info { - return snapshots.Info{ - Name: info.Name, - Parent: info.Parent, - Kind: toKind(info.Kind), - Created: protobuf.FromTimestamp(info.CreatedAt), - Updated: protobuf.FromTimestamp(info.UpdatedAt), - Labels: info.Labels, - } -} - -func toUsage(resp *snapshotsapi.UsageResponse) snapshots.Usage { - return snapshots.Usage{ - Inodes: resp.Inodes, - Size: resp.Size, - } -} - -func toMounts(mm []*types.Mount) []mount.Mount { - mounts := make([]mount.Mount, len(mm)) - for i, m := range mm { - mounts[i] = mount.Mount{ - Type: m.Type, - Source: m.Source, - Target: m.Target, - Options: m.Options, - } - } - return mounts -} - -func fromKind(kind snapshots.Kind) snapshotsapi.Kind { - if kind == snapshots.KindActive { - return snapshotsapi.Kind_ACTIVE - } - if kind == snapshots.KindView { - return snapshotsapi.Kind_VIEW - } - return snapshotsapi.Kind_COMMITTED -} - -func fromInfo(info snapshots.Info) *snapshotsapi.Info { - return &snapshotsapi.Info{ - Name: info.Name, - Parent: info.Parent, - Kind: fromKind(info.Kind), - CreatedAt: protobuf.ToTimestamp(info.Created), - UpdatedAt: protobuf.ToTimestamp(info.Updated), - Labels: info.Labels, - } + return errgrpc.ToNative(err) } diff --git a/vendor/github.com/containerd/containerd/snapshots/snapshotter.go b/vendor/github.com/containerd/containerd/v2/core/snapshots/snapshotter.go similarity index 99% rename from vendor/github.com/containerd/containerd/snapshots/snapshotter.go rename to vendor/github.com/containerd/containerd/v2/core/snapshots/snapshotter.go index 5fa5aa530c..5c07e90905 100644 --- a/vendor/github.com/containerd/containerd/snapshots/snapshotter.go +++ b/vendor/github.com/containerd/containerd/v2/core/snapshots/snapshotter.go @@ -22,7 +22,7 @@ import ( "strings" "time" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" ) const ( @@ -63,9 +63,9 @@ func ParseKind(s string) Kind { return KindActive case "committed": return KindCommitted + default: + return KindUnknown } - - return KindUnknown } // String returns the string representation of the Kind @@ -77,9 +77,9 @@ func (k Kind) String() string { return "Active" case KindCommitted: return "Committed" + default: + return "Unknown" } - - return "Unknown" } // MarshalJSON the Kind to JSON diff --git a/vendor/github.com/containerd/containerd/transfer.go b/vendor/github.com/containerd/containerd/v2/core/streaming/proxy/streaming.go similarity index 52% rename from vendor/github.com/containerd/containerd/transfer.go rename to vendor/github.com/containerd/containerd/v2/core/streaming/proxy/streaming.go index 9979aa75bd..fa47fc5d6b 100644 --- a/vendor/github.com/containerd/containerd/transfer.go +++ b/vendor/github.com/containerd/containerd/v2/core/streaming/proxy/streaming.go @@ -14,41 +14,61 @@ limitations under the License. */ -package containerd +package proxy import ( "context" "errors" + "fmt" "io" streamingapi "github.com/containerd/containerd/api/services/streaming/v1" - transferapi "github.com/containerd/containerd/api/services/transfer/v1" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/pkg/streaming" - "github.com/containerd/containerd/pkg/transfer" - "github.com/containerd/containerd/pkg/transfer/proxy" - "github.com/containerd/containerd/protobuf" + "github.com/containerd/errdefs" + "github.com/containerd/errdefs/pkg/errgrpc" + "github.com/containerd/ttrpc" "github.com/containerd/typeurl/v2" + "google.golang.org/grpc" + + "github.com/containerd/containerd/v2/core/streaming" ) -func (c *Client) Transfer(ctx context.Context, src interface{}, dest interface{}, opts ...transfer.Opt) error { - ctx, done, err := c.WithLease(ctx) - if err != nil { - return err +// NewStreamCreator returns a new stream creator which can communicate over a GRPC +// or TTRPC connection using the containerd streaming API. +func NewStreamCreator(client any) streaming.StreamCreator { + switch c := client.(type) { + case streamingapi.StreamingClient: + return &streamCreator{ + client: convertClient{c}, + } + case grpc.ClientConnInterface: + return &streamCreator{ + client: convertClient{streamingapi.NewStreamingClient(c)}, + } + case streamingapi.TTRPCStreamingClient: + return &streamCreator{ + client: c, + } + case *ttrpc.Client: + return &streamCreator{ + client: streamingapi.NewTTRPCStreamingClient(c), + } + case streaming.StreamCreator: + return c + default: + panic(fmt.Errorf("unsupported stream client %T: %w", client, errdefs.ErrNotImplemented)) } - defer done(ctx) - - return proxy.NewTransferrer(transferapi.NewTransferClient(c.conn), c.streamCreator()).Transfer(ctx, src, dest, opts...) } -func (c *Client) streamCreator() streaming.StreamCreator { - return &streamCreator{ - client: streamingapi.NewStreamingClient(c.conn), - } +type convertClient struct { + streamingapi.StreamingClient +} + +func (c convertClient) Stream(ctx context.Context) (streamingapi.TTRPCStreaming_StreamClient, error) { + return c.StreamingClient.Stream(ctx) } type streamCreator struct { - client streamingapi.StreamingClient + client streamingapi.TTRPCStreamingClient } func (sc *streamCreator) Create(ctx context.Context, id string) (streaming.Stream, error) { @@ -63,10 +83,10 @@ func (sc *streamCreator) Create(ctx context.Context, id string) (streaming.Strea if err != nil { return nil, err } - err = stream.Send(protobuf.FromAny(a)) + err = stream.Send(typeurl.MarshalProto(a)) if err != nil { if !errors.Is(err, io.EOF) { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) } return nil, err } @@ -74,7 +94,7 @@ func (sc *streamCreator) Create(ctx context.Context, id string) (streaming.Strea // Receive an ack that stream is init and ready if _, err = stream.Recv(); err != nil { if !errors.Is(err, io.EOF) { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) } return nil, err } @@ -85,13 +105,13 @@ func (sc *streamCreator) Create(ctx context.Context, id string) (streaming.Strea } type clientStream struct { - s streamingapi.Streaming_StreamClient + s streamingapi.TTRPCStreaming_StreamClient } func (cs *clientStream) Send(a typeurl.Any) (err error) { - err = cs.s.Send(protobuf.FromAny(a)) + err = cs.s.Send(typeurl.MarshalProto(a)) if !errors.Is(err, io.EOF) { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) } return } @@ -99,7 +119,7 @@ func (cs *clientStream) Send(a typeurl.Any) (err error) { func (cs *clientStream) Recv() (a typeurl.Any, err error) { a, err = cs.s.Recv() if !errors.Is(err, io.EOF) { - err = errdefs.FromGRPC(err) + err = errgrpc.ToNative(err) } return } diff --git a/vendor/github.com/containerd/containerd/pkg/streaming/streaming.go b/vendor/github.com/containerd/containerd/v2/core/streaming/streaming.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/streaming/streaming.go rename to vendor/github.com/containerd/containerd/v2/core/streaming/streaming.go diff --git a/vendor/github.com/containerd/containerd/pkg/transfer/proxy/transfer.go b/vendor/github.com/containerd/containerd/v2/core/transfer/proxy/transfer.go similarity index 61% rename from vendor/github.com/containerd/containerd/pkg/transfer/proxy/transfer.go rename to vendor/github.com/containerd/containerd/v2/core/transfer/proxy/transfer.go index 2ad7a94496..f314f6fe0a 100644 --- a/vendor/github.com/containerd/containerd/pkg/transfer/proxy/transfer.go +++ b/vendor/github.com/containerd/containerd/v2/core/transfer/proxy/transfer.go @@ -19,33 +19,70 @@ package proxy import ( "context" "errors" + "fmt" "io" + "google.golang.org/grpc" "google.golang.org/protobuf/types/known/anypb" + "google.golang.org/protobuf/types/known/emptypb" transferapi "github.com/containerd/containerd/api/services/transfer/v1" transfertypes "github.com/containerd/containerd/api/types/transfer" - "github.com/containerd/containerd/pkg/streaming" - "github.com/containerd/containerd/pkg/transfer" - tstreaming "github.com/containerd/containerd/pkg/transfer/streaming" + "github.com/containerd/containerd/v2/core/streaming" + "github.com/containerd/containerd/v2/core/transfer" + tstreaming "github.com/containerd/containerd/v2/core/transfer/streaming" + "github.com/containerd/containerd/v2/pkg/oci" + "github.com/containerd/errdefs" "github.com/containerd/log" + "github.com/containerd/ttrpc" "github.com/containerd/typeurl/v2" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) type proxyTransferrer struct { - client transferapi.TransferClient + client transferapi.TTRPCTransferService streamCreator streaming.StreamCreator } -// NewTransferrer returns a new transferrer which communicates over a GRPC -// connection using the containerd transfer API -func NewTransferrer(client transferapi.TransferClient, sc streaming.StreamCreator) transfer.Transferrer { - return &proxyTransferrer{ - client: client, - streamCreator: sc, +// NewTransferrer returns a new transferrer which can communicate over a GRPC +// or TTRPC connection using the containerd transfer API +func NewTransferrer(client any, sc streaming.StreamCreator) transfer.Transferrer { + switch c := client.(type) { + case transferapi.TransferClient: + return &proxyTransferrer{ + client: convertClient{c}, + streamCreator: sc, + } + case grpc.ClientConnInterface: + return &proxyTransferrer{ + client: convertClient{transferapi.NewTransferClient(c)}, + streamCreator: sc, + } + case transferapi.TTRPCTransferService: + return &proxyTransferrer{ + client: c, + streamCreator: sc, + } + case *ttrpc.Client: + return &proxyTransferrer{ + client: transferapi.NewTTRPCTransferClient(c), + streamCreator: sc, + } + case transfer.Transferrer: + return c + default: + panic(fmt.Errorf("unsupported stream client %T: %w", client, errdefs.ErrNotImplemented)) } } +type convertClient struct { + transferapi.TransferClient +} + +func (c convertClient) Transfer(ctx context.Context, r *transferapi.TransferRequest) (*emptypb.Empty, error) { + return c.TransferClient.Transfer(ctx, r) +} + func (p *proxyTransferrer) Transfer(ctx context.Context, src interface{}, dst interface{}, opts ...transfer.Opt) error { o := &transfer.Config{} for _, opt := range opts { @@ -74,12 +111,18 @@ func (p *proxyTransferrer) Transfer(ctx context.Context, src interface{}, dst in } switch v := i.(type) { case *transfertypes.Progress: + var descp *ocispec.Descriptor + if v.Desc != nil { + desc := oci.DescriptorFromProto(v.Desc) + descp = &desc + } o.Progress(transfer.Progress{ Event: v.Event, Name: v.Name, Parents: v.Parents, Progress: v.Progress, Total: v.Total, + Desc: descp, }) default: log.G(ctx).Warnf("unhandled progress object %T: %v", i, a.GetTypeUrl()) diff --git a/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/reader.go b/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/reader.go new file mode 100644 index 0000000000..e989b0d732 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/reader.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 streaming + +import ( + "context" + "errors" + "fmt" + "io" + + transferapi "github.com/containerd/containerd/api/types/transfer" + "github.com/containerd/containerd/v2/core/streaming" + "github.com/containerd/typeurl/v2" +) + +type readByteStream struct { + ctx context.Context + stream streaming.Stream + window int32 + updated chan struct{} + errCh chan error + remaining []byte +} + +func ReadByteStream(ctx context.Context, stream streaming.Stream) io.ReadCloser { + rbs := &readByteStream{ + ctx: ctx, + stream: stream, + window: 0, + errCh: make(chan error), + updated: make(chan struct{}, 1), + } + go func() { + for { + if rbs.window >= windowSize { + select { + case <-ctx.Done(): + return + case <-rbs.updated: + continue + } + } + update := &transferapi.WindowUpdate{ + Update: windowSize, + } + anyType, err := typeurl.MarshalAny(update) + if err != nil { + rbs.errCh <- err + return + } + if err := stream.Send(anyType); err == nil { + rbs.window += windowSize + } else if !errors.Is(err, io.EOF) { + rbs.errCh <- err + } + } + + }() + return rbs +} + +func (r *readByteStream) Read(p []byte) (n int, err error) { + plen := len(p) + if len(r.remaining) > 0 { + copied := copy(p, r.remaining) + if len(r.remaining) > plen { + r.remaining = r.remaining[plen:] + } else { + r.remaining = nil + } + return copied, nil + } + select { + case <-r.ctx.Done(): + return 0, r.ctx.Err() + case err := <-r.errCh: + return 0, err + default: + } + anyType, err := r.stream.Recv() + if err != nil { + return 0, err + } + i, err := typeurl.UnmarshalAny(anyType) + if err != nil { + return 0, err + } + switch v := i.(type) { + case *transferapi.Data: + n := copy(p, v.Data) + if len(v.Data) > plen { + r.remaining = v.Data[plen:] + } + r.window = r.window - int32(n) + if r.window < windowSize { + r.updated <- struct{}{} + } + return n, nil + default: + return 0, fmt.Errorf("stream received error type %v", v) + } + +} + +func (r *readByteStream) Close() error { + return r.stream.Close() +} diff --git a/vendor/github.com/containerd/containerd/pkg/transfer/streaming/stream.go b/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/stream.go similarity index 92% rename from vendor/github.com/containerd/containerd/pkg/transfer/streaming/stream.go rename to vendor/github.com/containerd/containerd/v2/core/transfer/streaming/stream.go index 0028146b92..caea29536b 100644 --- a/vendor/github.com/containerd/containerd/pkg/transfer/streaming/stream.go +++ b/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/stream.go @@ -27,7 +27,7 @@ import ( "time" transferapi "github.com/containerd/containerd/api/types/transfer" - "github.com/containerd/containerd/pkg/streaming" + "github.com/containerd/containerd/v2/core/streaming" "github.com/containerd/log" "github.com/containerd/typeurl/v2" ) @@ -53,14 +53,14 @@ func SendStream(ctx context.Context, r io.Reader, stream streaming.Stream) { default: } - any, err := stream.Recv() + anyType, err := stream.Recv() if err != nil { if !errors.Is(err, io.EOF) && !errors.Is(err, context.Canceled) { log.G(ctx).WithError(err).Error("send stream ended without EOF") } return } - i, err := typeurl.UnmarshalAny(any) + i, err := typeurl.UnmarshalAny(anyType) if err != nil { log.G(ctx).WithError(err).Error("failed to unmarshal stream object") continue @@ -124,13 +124,13 @@ func SendStream(ctx context.Context, r io.Reader, stream streaming.Stream) { data := &transferapi.Data{ Data: b[:n], } - any, err := typeurl.MarshalAny(data) + anyType, err := typeurl.MarshalAny(data) if err != nil { log.G(ctx).WithError(err).Errorf("failed to marshal data for send") // TODO: Send error message on stream before close to allow remote side to return error return } - if err := stream.Send(any); err != nil { + if err := stream.Send(anyType); err != nil { log.G(ctx).WithError(err).Errorf("send failed") return } @@ -149,20 +149,20 @@ func ReceiveStream(ctx context.Context, stream streaming.Stream) io.Reader { update := &transferapi.WindowUpdate{ Update: windowSize, } - any, err := typeurl.MarshalAny(update) + anyType, err := typeurl.MarshalAny(update) if err != nil { w.CloseWithError(fmt.Errorf("failed to marshal window update: %w", err)) return } // check window update error after recv, stream may be complete - if werr = stream.Send(any); werr == nil { + if werr = stream.Send(anyType); werr == nil { window += windowSize } else if errors.Is(werr, io.EOF) { // TODO: Why does send return EOF here werr = nil } } - any, err := stream.Recv() + anyType, err := stream.Recv() if err != nil { if errors.Is(err, io.EOF) || errors.Is(err, context.Canceled) { err = nil @@ -176,7 +176,7 @@ func ReceiveStream(ctx context.Context, stream streaming.Stream) io.Reader { w.CloseWithError(fmt.Errorf("failed to send window update: %w", werr)) return } - i, err := typeurl.UnmarshalAny(any) + i, err := typeurl.UnmarshalAny(anyType) if err != nil { w.CloseWithError(fmt.Errorf("failed to unmarshal received object: %w", err)) return diff --git a/vendor/github.com/containerd/containerd/pkg/transfer/streaming/writer.go b/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/writer.go similarity index 91% rename from vendor/github.com/containerd/containerd/pkg/transfer/streaming/writer.go rename to vendor/github.com/containerd/containerd/v2/core/transfer/streaming/writer.go index f8f372d2b0..4e13b33bb2 100644 --- a/vendor/github.com/containerd/containerd/pkg/transfer/streaming/writer.go +++ b/vendor/github.com/containerd/containerd/v2/core/transfer/streaming/writer.go @@ -23,7 +23,7 @@ import ( "sync/atomic" transferapi "github.com/containerd/containerd/api/types/transfer" - "github.com/containerd/containerd/pkg/streaming" + "github.com/containerd/containerd/v2/core/streaming" "github.com/containerd/log" "github.com/containerd/typeurl/v2" ) @@ -42,14 +42,14 @@ func WriteByteStream(ctx context.Context, stream streaming.Stream) io.WriteClose default: } - any, err := stream.Recv() + anyType, err := stream.Recv() if err != nil { if !errors.Is(err, io.EOF) && !errors.Is(err, context.Canceled) { log.G(ctx).WithError(err).Error("send byte stream ended without EOF") } return } - i, err := typeurl.UnmarshalAny(any) + i, err := typeurl.UnmarshalAny(anyType) if err != nil { log.G(ctx).WithError(err).Error("failed to unmarshal stream object") continue @@ -102,19 +102,19 @@ func (wbs *writeByteStream) Write(p []byte) (n int, err error) { max = remaining } // TODO: continue - //remaining = remaining - int32(n) + // remaining = remaining - int32(n) data := &transferapi.Data{ Data: p[:max], } - var any typeurl.Any - any, err = typeurl.MarshalAny(data) + var anyType typeurl.Any + anyType, err = typeurl.MarshalAny(data) if err != nil { log.G(wbs.ctx).WithError(err).Errorf("failed to marshal data for send") // TODO: Send error message on stream before close to allow remote side to return error return } - if err = wbs.stream.Send(any); err != nil { + if err = wbs.stream.Send(anyType); err != nil { log.G(wbs.ctx).WithError(err).Errorf("send failed") return } diff --git a/vendor/github.com/containerd/containerd/pkg/transfer/transfer.go b/vendor/github.com/containerd/containerd/v2/core/transfer/transfer.go similarity index 92% rename from vendor/github.com/containerd/containerd/pkg/transfer/transfer.go rename to vendor/github.com/containerd/containerd/v2/core/transfer/transfer.go index 01df8c3d39..0329bfcfbb 100644 --- a/vendor/github.com/containerd/containerd/pkg/transfer/transfer.go +++ b/vendor/github.com/containerd/containerd/v2/core/transfer/transfer.go @@ -22,8 +22,8 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" ) type Transferrer interface { @@ -100,6 +100,11 @@ type ImageUnpacker interface { UnpackPlatforms() []UnpackConfiguration } +// ImagePlatformsGetter is type which returns configured platforms. +type ImagePlatformsGetter interface { + Platforms() []ocispec.Platform +} + // UnpackConfiguration specifies the platform and snapshotter to use for resolving // the unpack Platform, if snapshotter is not specified the platform default will // be used. @@ -132,5 +137,5 @@ type Progress struct { Parents []string Progress int64 Total int64 - // Descriptor? + Desc *ocispec.Descriptor // since containerd v2.0 } diff --git a/vendor/github.com/containerd/containerd/pkg/unpack/unpacker.go b/vendor/github.com/containerd/containerd/v2/core/unpack/unpacker.go similarity index 95% rename from vendor/github.com/containerd/containerd/pkg/unpack/unpacker.go rename to vendor/github.com/containerd/containerd/v2/core/unpack/unpacker.go index 773722a088..90385856a6 100644 --- a/vendor/github.com/containerd/containerd/pkg/unpack/unpacker.go +++ b/vendor/github.com/containerd/containerd/v2/core/unpack/unpacker.go @@ -28,6 +28,16 @@ import ( "sync/atomic" "time" + "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/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/internal/cleanup" + "github.com/containerd/containerd/v2/internal/kmutex" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/tracing" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/containerd/platforms" "github.com/opencontainers/go-digest" @@ -35,17 +45,6 @@ import ( ocispec "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sync/errgroup" "golang.org/x/sync/semaphore" - - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/pkg/cleanup" - "github.com/containerd/containerd/pkg/kmutex" - "github.com/containerd/containerd/snapshots" - "github.com/containerd/containerd/tracing" ) const ( @@ -180,8 +179,7 @@ func (u *Unpacker) Unpack(h images.Handler) images.Handler { return children, err } - switch desc.MediaType { - case images.MediaTypeDockerSchema2Manifest, ocispec.MediaTypeImageManifest: + if images.IsManifestType(desc.MediaType) { var nonLayers []ocispec.Descriptor var manifestLayers []ocispec.Descriptor // Split layers from non-layers, layers will be handled after @@ -204,7 +202,7 @@ func (u *Unpacker) Unpack(h images.Handler) images.Handler { lock.Unlock() children = nonLayers - case images.MediaTypeDockerSchema2Config, ocispec.MediaTypeImageConfig: + } else if images.IsConfigType(desc.MediaType) { lock.Lock() l := layers[desc.Digest] lock.Unlock() @@ -255,7 +253,7 @@ func (u *Unpacker) unpack( // TODO: Support multiple unpacks rather than just first match var unpack *Platform - imgPlatform := platforms.Normalize(ocispec.Platform{OS: i.OS, Architecture: i.Architecture}) + imgPlatform := platforms.Normalize(i.Platform) for _, up := range u.platforms { if up.Platform.Match(imgPlatform) { unpack = up diff --git a/vendor/github.com/containerd/containerd/defaults/defaults.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults.go similarity index 100% rename from vendor/github.com/containerd/containerd/defaults/defaults.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults.go diff --git a/vendor/github.com/containerd/containerd/defaults/defaults_darwin.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_darwin.go similarity index 100% rename from vendor/github.com/containerd/containerd/defaults/defaults_darwin.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_darwin.go diff --git a/vendor/github.com/containerd/containerd/v2/defaults/defaults_differ_windows.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_differ_windows.go new file mode 100644 index 0000000000..0762d259ee --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_differ_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 defaults + +const ( + // DefaultDiffer will set the default differ for the platform. + // This differ should be compatible with the windows snapshotter. + DefaultDiffer = "windows" +) diff --git a/vendor/github.com/containerd/containerd/services/introspection/pidns_others.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_freebsd.go similarity index 84% rename from vendor/github.com/containerd/containerd/services/introspection/pidns_others.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_freebsd.go index c2cc475af3..d74133012a 100644 --- a/vendor/github.com/containerd/containerd/services/introspection/pidns_others.go +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_freebsd.go @@ -1,5 +1,3 @@ -//go:build !linux - /* Copyright The containerd Authors. @@ -16,8 +14,9 @@ limitations under the License. */ -package introspection +package defaults -func statPIDNS(pid int) (uint64, error) { - return 0, nil -} +const ( + // DefaultRuntime is the default freebsd runtime + DefaultRuntime = "wtf.sbk.runj.v1" +) diff --git a/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/doc.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_linux.go similarity index 83% rename from vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/doc.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_linux.go index 9617e74043..7187c5a767 100644 --- a/vendor/github.com/containerd/containerd/pkg/runtimeoptions/v1/doc.go +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_linux.go @@ -14,4 +14,9 @@ limitations under the License. */ -package runtimeoptions_v1 //nolint:revive // Ignore var-naming: don't use an underscore in package name (revive) +package defaults + +const ( + // DefaultRuntime is the default linux runtime + DefaultRuntime = "io.containerd.runc.v2" +) diff --git a/vendor/github.com/containerd/containerd/snapshotter_default_linux.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_linux.go similarity index 97% rename from vendor/github.com/containerd/containerd/snapshotter_default_linux.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_linux.go index d925d4ef94..ade1947177 100644 --- a/vendor/github.com/containerd/containerd/snapshotter_default_linux.go +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_linux.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package defaults const ( // DefaultSnapshotter will set the default snapshotter for the platform. diff --git a/vendor/github.com/containerd/containerd/snapshotter_default_unix.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_unix.go similarity index 97% rename from vendor/github.com/containerd/containerd/snapshotter_default_unix.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_unix.go index 8e191ca6ac..fc8b081ff8 100644 --- a/vendor/github.com/containerd/containerd/snapshotter_default_unix.go +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_unix.go @@ -16,7 +16,7 @@ limitations under the License. */ -package containerd +package defaults const ( // DefaultSnapshotter will set the default snapshotter for the platform. diff --git a/vendor/github.com/containerd/containerd/snapshotter_default_windows.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_windows.go similarity index 97% rename from vendor/github.com/containerd/containerd/snapshotter_default_windows.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_windows.go index 320211a4a5..37e5f7574d 100644 --- a/vendor/github.com/containerd/containerd/snapshotter_default_windows.go +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_snapshotter_windows.go @@ -14,7 +14,7 @@ limitations under the License. */ -package containerd +package defaults const ( // DefaultSnapshotter will set the default snapshotter for the platform. diff --git a/vendor/github.com/containerd/containerd/defaults/defaults_unix.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_unix.go similarity index 93% rename from vendor/github.com/containerd/containerd/defaults/defaults_unix.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_unix.go index c79f9ba7df..e68a522cad 100644 --- a/vendor/github.com/containerd/containerd/defaults/defaults_unix.go +++ b/vendor/github.com/containerd/containerd/v2/defaults/defaults_unix.go @@ -32,8 +32,6 @@ const ( // DefaultFIFODir is the default location used by client-side cio library // to store FIFOs. DefaultFIFODir = "/run/containerd/fifo" - // DefaultRuntime is the default linux runtime - DefaultRuntime = "io.containerd.runc.v2" // DefaultConfigDir is the default location for config files. DefaultConfigDir = "/etc/containerd" ) diff --git a/vendor/github.com/containerd/containerd/defaults/defaults_windows.go b/vendor/github.com/containerd/containerd/v2/defaults/defaults_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/defaults/defaults_windows.go rename to vendor/github.com/containerd/containerd/v2/defaults/defaults_windows.go diff --git a/vendor/github.com/containerd/containerd/defaults/doc.go b/vendor/github.com/containerd/containerd/v2/defaults/doc.go similarity index 100% rename from vendor/github.com/containerd/containerd/defaults/doc.go rename to vendor/github.com/containerd/containerd/v2/defaults/doc.go diff --git a/vendor/github.com/containerd/containerd/pkg/cleanup/context.go b/vendor/github.com/containerd/containerd/v2/internal/cleanup/context.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/cleanup/context.go rename to vendor/github.com/containerd/containerd/v2/internal/cleanup/context.go diff --git a/vendor/github.com/containerd/containerd/v2/internal/fsverity/fsverity_linux.go b/vendor/github.com/containerd/containerd/v2/internal/fsverity/fsverity_linux.go new file mode 100644 index 0000000000..6b55666d82 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/internal/fsverity/fsverity_linux.go @@ -0,0 +1,130 @@ +/* + 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 fsverity + +import ( + "fmt" + "os" + "path/filepath" + "syscall" + "unsafe" + + "github.com/containerd/containerd/v2/pkg/kernelversion" + "golang.org/x/sys/unix" +) + +type fsverityEnableArg struct { + version uint32 + hashAlgorithm uint32 + blockSize uint32 + saltSize uint32 + saltPtr uint64 + sigSize uint32 + reserved1 uint32 + sigPtr uint64 + reserved2 [11]uint64 +} + +const ( + defaultBlockSize int = 4096 + maxDigestSize uint16 = 64 +) + +func IsSupported(rootPath string) (bool, error) { + minKernelVersion := kernelversion.KernelVersion{Kernel: 5, Major: 4} + s, err := kernelversion.GreaterEqualThan(minKernelVersion) + if err != nil { + return s, err + } + + integrityDir, err := os.MkdirTemp(rootPath, ".fsverity-check-*") + if err != nil { + return false, err + } + defer os.RemoveAll(integrityDir) + + digestPath := filepath.Join(integrityDir, "supported") + digestFile, err := os.Create(digestPath) + if err != nil { + return false, err + } + + digestFile.Close() + + eerr := Enable(digestPath) + if eerr != nil { + return false, eerr + } + + return true, nil +} + +func IsEnabled(path string) (bool, error) { + f, err := os.Open(path) + if err != nil { + return false, err + } + defer f.Close() + + var attr int32 + + _, _, flagErr := unix.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(unix.FS_IOC_GETFLAGS), uintptr(unsafe.Pointer(&attr))) + if flagErr != 0 { + return false, fmt.Errorf("error getting inode flags: %w", flagErr) + } + + if attr&unix.FS_VERITY_FL == unix.FS_VERITY_FL { + return true, nil + } + + return false, nil +} + +func Enable(path string) error { + f, err := os.Open(path) + if err != nil { + return err + } + + var args = &fsverityEnableArg{} + args.version = 1 + args.hashAlgorithm = 1 + + // fsverity block size should be the minimum between the page size + // and the file system block size + // If neither value is retrieved successfully, set fsverity block size to the default value + blockSize := unix.Getpagesize() + + s := unix.Stat_t{} + serr := unix.Stat(path, &s) + if serr == nil && int(s.Blksize) < blockSize { + blockSize = int(s.Blksize) + } + + if blockSize <= 0 { + blockSize = defaultBlockSize + } + + args.blockSize = uint32(blockSize) + + _, _, errno := unix.Syscall(syscall.SYS_IOCTL, f.Fd(), uintptr(unix.FS_IOC_ENABLE_VERITY), uintptr(unsafe.Pointer(args))) + if errno != 0 { + return fmt.Errorf("enable fsverity failed: %w", errno) + } + + return nil +} diff --git a/vendor/github.com/containerd/containerd/v2/internal/fsverity/fsverity_other.go b/vendor/github.com/containerd/containerd/v2/internal/fsverity/fsverity_other.go new file mode 100644 index 0000000000..f50789adab --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/internal/fsverity/fsverity_other.go @@ -0,0 +1,33 @@ +//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 fsverity + +import "fmt" + +func IsSupported(rootPath string) (bool, error) { + return false, fmt.Errorf("fsverity is only supported on Linux systems") +} + +func IsEnabled(path string) (bool, error) { + return false, fmt.Errorf("fsverity is only supported on Linux systems") +} + +func Enable(_ string) error { + return fmt.Errorf("fsverity is only supported on Linux systems") +} diff --git a/vendor/github.com/containerd/containerd/pkg/kmutex/kmutex.go b/vendor/github.com/containerd/containerd/v2/internal/kmutex/kmutex.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/kmutex/kmutex.go rename to vendor/github.com/containerd/containerd/v2/internal/kmutex/kmutex.go diff --git a/vendor/github.com/containerd/containerd/pkg/kmutex/noop.go b/vendor/github.com/containerd/containerd/v2/internal/kmutex/noop.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/kmutex/noop.go rename to vendor/github.com/containerd/containerd/v2/internal/kmutex/noop.go diff --git a/vendor/github.com/containerd/containerd/pkg/randutil/randutil.go b/vendor/github.com/containerd/containerd/v2/internal/randutil/randutil.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/randutil/randutil.go rename to vendor/github.com/containerd/containerd/v2/internal/randutil/randutil.go diff --git a/vendor/github.com/containerd/containerd/v2/internal/userns/idmap.go b/vendor/github.com/containerd/containerd/v2/internal/userns/idmap.go new file mode 100644 index 0000000000..e547419a89 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/internal/userns/idmap.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. +*/ + +/* + This file is copied and customized based on + https://github.com/moby/moby/blob/master/pkg/idtools/idtools.go +*/ + +package userns + +import ( + "errors" + "fmt" + + "github.com/opencontainers/runtime-spec/specs-go" +) + +const invalidID = 1<<32 - 1 + +var invalidUser = User{Uid: invalidID, Gid: invalidID} + +// User is a Uid and Gid pair of a user +// +//nolint:revive +type User struct { + Uid uint32 + Gid uint32 +} + +// IDMap contains the mappings of Uids and Gids. +// +//nolint:revive +type IDMap struct { + UidMap []specs.LinuxIDMapping `json:"UidMap"` + GidMap []specs.LinuxIDMapping `json:"GidMap"` +} + +// ToHost returns the host user ID pair for the container ID pair. +func (i IDMap) ToHost(pair User) (User, error) { + var ( + target User + err error + ) + target.Uid, err = toHost(pair.Uid, i.UidMap) + if err != nil { + return invalidUser, err + } + target.Gid, err = toHost(pair.Gid, i.GidMap) + if err != nil { + return invalidUser, err + } + return target, nil +} + +// toHost takes an id mapping and a remapped ID, and translates the +// ID to the mapped host ID. If no map is provided, then the translation +// assumes a 1-to-1 mapping and returns the passed in id # +func toHost(contID uint32, idMap []specs.LinuxIDMapping) (uint32, error) { + if idMap == nil { + return contID, nil + } + for _, m := range idMap { + high, err := safeSum(m.ContainerID, m.Size) + if err != nil { + break + } + if contID >= m.ContainerID && contID < high { + hostID, err := safeSum(m.HostID, contID-m.ContainerID) + if err != nil || hostID == invalidID { + break + } + return hostID, nil + } + } + return invalidID, fmt.Errorf("container ID %d cannot be mapped to a host ID", contID) +} + +// safeSum returns the sum of x and y. or an error if the result overflows +func safeSum(x, y uint32) (uint32, error) { + z := x + y + if z < x || z < y { + return invalidID, errors.New("ID overflow") + } + return z, nil +} diff --git a/vendor/github.com/containerd/containerd/pkg/apparmor/apparmor.go b/vendor/github.com/containerd/containerd/v2/pkg/apparmor/apparmor.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/apparmor/apparmor.go rename to vendor/github.com/containerd/containerd/v2/pkg/apparmor/apparmor.go diff --git a/vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/apparmor/apparmor_linux.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/apparmor/apparmor_linux.go diff --git a/vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_unsupported.go b/vendor/github.com/containerd/containerd/v2/pkg/apparmor/apparmor_unsupported.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/apparmor/apparmor_unsupported.go rename to vendor/github.com/containerd/containerd/v2/pkg/apparmor/apparmor_unsupported.go diff --git a/vendor/github.com/containerd/containerd/archive/compression/compression.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/compression/compression.go similarity index 85% rename from vendor/github.com/containerd/containerd/archive/compression/compression.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/compression/compression.go index 23ddfab1a6..cba5e477cd 100644 --- a/vendor/github.com/containerd/containerd/archive/compression/compression.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/archive/compression/compression.go @@ -45,13 +45,18 @@ const ( Gzip // Zstd is zstd compression algorithm. Zstd + // Unknown is used when a plugin handles the algorithm. + Unknown ) -const disablePigzEnv = "CONTAINERD_DISABLE_PIGZ" +const ( + disablePigzEnv = "CONTAINERD_DISABLE_PIGZ" + disableIgzipEnv = "CONTAINERD_DISABLE_IGZIP" +) var ( - initPigz sync.Once - unpigzPath string + initGzip sync.Once + gzipPath string ) var ( @@ -146,7 +151,7 @@ func magicNumberMatcher(m []byte) matcher { // zstdMatcher detects zstd compression algorithm. // There are two frame formats defined by Zstandard: Zstandard frames and Skippable frames. -// See https://tools.ietf.org/id/draft-kucherawy-dispatch-zstd-00.html#rfc.section.2 for more details. +// See https://datatracker.ietf.org/doc/html/rfc8878#section-3 for more details. func zstdMatcher() matcher { return func(source []byte) bool { if bytes.HasPrefix(source, zstdMagic) { @@ -254,22 +259,27 @@ func (compression *Compression) Extension() string { return "gz" case Zstd: return "zst" + case Unknown: + return "unknown" } return "" } func gzipDecompress(ctx context.Context, buf io.Reader) (io.ReadCloser, error) { - initPigz.Do(func() { - if unpigzPath = detectPigz(); unpigzPath != "" { - log.L.Debug("using pigz for decompression") + initGzip.Do(func() { + if gzipPath = detectCommand("igzip", disableIgzipEnv); gzipPath != "" { + log.L.Debug("using igzip for decompression") + return + } + if gzipPath = detectCommand("unpigz", disablePigzEnv); gzipPath != "" { + log.L.Debug("using unpigz for decompression") } }) - if unpigzPath == "" { + if gzipPath == "" { return gzip.NewReader(buf) } - - return cmdStream(exec.CommandContext(ctx, unpigzPath, "-d", "-c"), buf) + return cmdStream(exec.CommandContext(ctx, gzipPath, "-d", "-c"), buf) } func cmdStream(cmd *exec.Cmd, in io.Reader) (io.ReadCloser, error) { @@ -296,26 +306,23 @@ func cmdStream(cmd *exec.Cmd, in io.Reader) (io.ReadCloser, error) { return reader, nil } -func detectPigz() string { - path, err := exec.LookPath("unpigz") +func detectCommand(path, disableEnvName string) string { + // Check if this command is disabled via the env variable + value := os.Getenv(disableEnvName) + if value != "" { + disable, err := strconv.ParseBool(value) + if err != nil { + log.L.WithError(err).Warnf("could not parse %s: %s", disableEnvName, value) + } + + if disable { + return "" + } + } + + path, err := exec.LookPath(path) if err != nil { - log.L.WithError(err).Debug("unpigz not found, falling back to go gzip") - return "" - } - - // Check if pigz disabled via CONTAINERD_DISABLE_PIGZ env variable - value := os.Getenv(disablePigzEnv) - if value == "" { - return path - } - - disable, err := strconv.ParseBool(value) - if err != nil { - log.L.WithError(err).Warnf("could not parse %s: %s", disablePigzEnv, value) - return path - } - - if disable { + log.L.WithError(err).Debugf("%s not found", path) return "" } diff --git a/vendor/github.com/containerd/containerd/archive/compression/compression_fuzzer.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/compression/compression_fuzzer.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/compression/compression_fuzzer.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/compression/compression_fuzzer.go diff --git a/vendor/github.com/containerd/containerd/archive/link_default.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/link_default.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/link_default.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/link_default.go diff --git a/vendor/github.com/containerd/containerd/services/introspection/pidns_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/link_freebsd.go similarity index 64% rename from vendor/github.com/containerd/containerd/services/introspection/pidns_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/link_freebsd.go index 4dce1a5e7b..28251e4709 100644 --- a/vendor/github.com/containerd/containerd/services/introspection/pidns_linux.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/archive/link_freebsd.go @@ -14,23 +14,21 @@ limitations under the License. */ -package introspection +package archive import ( - "fmt" "os" - "syscall" + + "github.com/containerd/containerd/v2/pkg/sys" + "golang.org/x/sys/unix" ) -func statPIDNS(pid int) (uint64, error) { - f := fmt.Sprintf("/proc/%d/ns/pid", pid) - st, err := os.Stat(f) - if err != nil { - return 0, err +func link(oldname, newname string) error { + e := sys.IgnoringEINTR(func() error { + return unix.Linkat(unix.AT_FDCWD, oldname, unix.AT_FDCWD, newname, 0) + }) + if e != nil { + return &os.LinkError{Op: "link", Old: oldname, New: newname, Err: e} } - stSys, ok := st.Sys().(*syscall.Stat_t) - if !ok { - return 0, fmt.Errorf("%T is not *syscall.Stat_t", st.Sys()) - } - return stSys.Ino, nil + return nil } diff --git a/vendor/github.com/containerd/containerd/archive/tar.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar.go similarity index 96% rename from vendor/github.com/containerd/containerd/archive/tar.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar.go index 21ab7f8114..d4cb42213e 100644 --- a/vendor/github.com/containerd/containerd/archive/tar.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar.go @@ -31,8 +31,8 @@ import ( "github.com/moby/sys/userns" - "github.com/containerd/containerd/archive/tarheader" - "github.com/containerd/containerd/pkg/epoch" + "github.com/containerd/containerd/v2/pkg/archive/tarheader" + "github.com/containerd/containerd/v2/pkg/epoch" "github.com/containerd/continuity/fs" "github.com/containerd/log" ) @@ -104,9 +104,9 @@ func WriteDiff(ctx context.Context, w io.Writer, a, b string, opts ...WriteDiffO func writeDiffNaive(ctx context.Context, w io.Writer, a, b string, o WriteDiffOptions) error { var opts []ChangeWriterOpt if o.SourceDateEpoch != nil { - opts = append(opts, - WithModTimeUpperBound(*o.SourceDateEpoch), - WithWhiteoutTime(*o.SourceDateEpoch)) + opts = append(opts, WithModTimeUpperBound(*o.SourceDateEpoch)) + // Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01), + // not to the source date epoch } cw := NewChangeWriter(w, b, opts...) err := fs.Changes(ctx, a, b, cw.HandleChange) @@ -343,7 +343,7 @@ func createTarFile(ctx context.Context, path, extractDir string, hdr *tar.Header } } - //nolint:staticcheck // Ignore SA1019. TypeRegA is deprecated but we may still receive an external tar with TypeRegA + //nolint:staticcheck // TypeRegA is deprecated but we may still receive an external tar with TypeRegA case tar.TypeReg, tar.TypeRegA: file, err := openFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, hdrInfo.Mode()) if err != nil { @@ -506,7 +506,6 @@ type ChangeWriter struct { tw *tar.Writer source string modTimeUpperBound *time.Time - whiteoutT time.Time inodeSrc map[uint64]string inodeRefs map[uint64][]string addedDirs map[string]struct{} @@ -522,13 +521,6 @@ func WithModTimeUpperBound(tm time.Time) ChangeWriterOpt { } } -// WithWhiteoutTime sets the whiteout timestamp. -func WithWhiteoutTime(tm time.Time) ChangeWriterOpt { - return func(cw *ChangeWriter) { - cw.whiteoutT = tm - } -} - // NewChangeWriter returns ChangeWriter that writes tar stream of the source directory // to the privided writer. Change information (add/modify/delete/unmodified) for each // file needs to be passed through HandleChange method. @@ -536,7 +528,6 @@ func NewChangeWriter(w io.Writer, source string, opts ...ChangeWriterOpt) *Chang cw := &ChangeWriter{ tw: tar.NewWriter(w), source: source, - whiteoutT: time.Now(), // can be overridden with WithWhiteoutTime(time.Time) ChangeWriterOpt . inodeSrc: map[uint64]string{}, inodeRefs: map[uint64][]string{}, addedDirs: map[string]struct{}{}, @@ -558,13 +549,16 @@ func (cw *ChangeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e whiteOutDir := filepath.Dir(p) whiteOutBase := filepath.Base(p) whiteOut := filepath.Join(whiteOutDir, whiteoutPrefix+whiteOutBase) + // Since containerd v2.0, the whiteout timestamps are set to zero (1970-01-01), + // not to the source date epoch. + whiteOutT := time.Unix(0, 0).UTC() hdr := &tar.Header{ Typeflag: tar.TypeReg, Name: whiteOut[1:], Size: 0, - ModTime: cw.whiteoutT, - AccessTime: cw.whiteoutT, - ChangeTime: cw.whiteoutT, + ModTime: whiteOutT, + AccessTime: whiteOutT, + ChangeTime: whiteOutT, } if err := cw.includeParents(hdr); err != nil { return err @@ -673,7 +667,7 @@ func (cw *ChangeWriter) HandleChange(k fs.ChangeKind, p string, f os.FileInfo, e n, err := copyBuffered(context.TODO(), cw.tw, file) if err != nil { - return fmt.Errorf("failed to copy: %w", err) + return fmt.Errorf("failed to copy: %v: %w", source, err) } if n != hdr.Size { return errors.New("short write copying file") diff --git a/vendor/github.com/containerd/containerd/archive/tar_freebsd.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_freebsd.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/tar_freebsd.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_freebsd.go diff --git a/vendor/github.com/containerd/containerd/archive/tar_mostunix.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_mostunix.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/tar_mostunix.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_mostunix.go diff --git a/vendor/github.com/containerd/containerd/archive/tar_opts.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/tar_opts.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts.go diff --git a/vendor/github.com/containerd/containerd/archive/tar_opts_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts_linux.go similarity index 91% rename from vendor/github.com/containerd/containerd/archive/tar_opts_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts_linux.go index f88d826e49..e400dd40ec 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_opts_linux.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts_linux.go @@ -25,11 +25,6 @@ import ( "golang.org/x/sys/unix" ) -// AufsConvertWhiteout converts whiteout files for aufs. -func AufsConvertWhiteout(_ *tar.Header, _ string) (bool, error) { - return true, nil -} - // OverlayConvertWhiteout converts whiteout files for overlay. func OverlayConvertWhiteout(hdr *tar.Header, path string) (bool, error) { base := filepath.Base(path) diff --git a/vendor/github.com/containerd/containerd/archive/tar_opts_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts_windows.go similarity index 70% rename from vendor/github.com/containerd/containerd/archive/tar_opts_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts_windows.go index 0ba3cd0822..3ec253f497 100644 --- a/vendor/github.com/containerd/containerd/archive/tar_opts_windows.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_opts_windows.go @@ -20,13 +20,23 @@ import ( "context" "io" + "github.com/Microsoft/go-winio" "github.com/Microsoft/hcsshim/pkg/ociwclayer" + ocicimlayer "github.com/Microsoft/hcsshim/pkg/ociwclayer/cim" ) // applyWindowsLayer applies a tar stream of an OCI style diff tar of a Windows layer // See https://github.com/opencontainers/image-spec/blob/main/layer.md#applying-changesets func applyWindowsLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) { - return ociwclayer.ImportLayerFromTar(ctx, r, root, options.Parents) + // It seems that in certain situations, like having the containerd root and state on a file system hosted on a + // mounted VHDX, we need SeSecurityPrivilege when opening a file with winio.ACCESS_SYSTEM_SECURITY. This happens + // in the base layer writer in hcsshim when adding a new file. + err = winio.RunWithPrivileges([]string{winio.SeSecurityPrivilege}, func() error { + var innerErr error + size, innerErr = ociwclayer.ImportLayerFromTar(ctx, r, root, options.Parents) + return innerErr + }) + return } // AsWindowsContainerLayer indicates that the tar stream to apply is that of @@ -68,3 +78,16 @@ func WithParentLayers(p []string) WriteDiffOpt { return nil } } + +func applyWindowsCimLayer(ctx context.Context, root string, r io.Reader, options ApplyOptions) (size int64, err error) { + return ocicimlayer.ImportCimLayerFromTar(ctx, r, root, options.Parents) +} + +// AsCimContainerLayer indicates that the tar stream to apply is that of a Windows container Layer written in +// the cim format. +func AsCimContainerLayer() ApplyOpt { + return func(options *ApplyOptions) error { + options.applyFunc = applyWindowsCimLayer + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/archive/tar_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/tar_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_unix.go diff --git a/vendor/github.com/containerd/containerd/archive/tar_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tar_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/tar_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tar_windows.go diff --git a/vendor/github.com/containerd/containerd/archive/tarheader/tarheader.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tarheader/tarheader.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/tarheader/tarheader.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tarheader/tarheader.go diff --git a/vendor/github.com/containerd/containerd/archive/tarheader/tarheader_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/tarheader/tarheader_unix.go similarity index 63% rename from vendor/github.com/containerd/containerd/archive/tarheader/tarheader_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/tarheader/tarheader_unix.go index 98ad8f9451..e9e2ea3745 100644 --- a/vendor/github.com/containerd/containerd/archive/tarheader/tarheader_unix.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/archive/tarheader/tarheader_unix.go @@ -28,6 +28,7 @@ package tarheader import ( "archive/tar" "os" + "runtime" "syscall" "golang.org/x/sys/unix" @@ -39,7 +40,7 @@ func init() { // statUnix populates hdr from system-dependent fields of fi without performing // any OS lookups. -// From https://github.com/moby/moby/blob/v23.0.1/pkg/archive/archive_unix.go#L52-L70 +// From https://github.com/moby/moby/blob/2cccb1f02c83aaacef3c15fa43f3b64d57f315f8/pkg/archive/archive_unix.go#L46-L76 func statUnix(fi os.FileInfo, hdr *tar.Header) error { s, ok := fi.Sys().(*syscall.Stat_t) if !ok { @@ -49,6 +50,21 @@ func statUnix(fi os.FileInfo, hdr *tar.Header) error { hdr.Uid = int(s.Uid) hdr.Gid = int(s.Gid) + // Devmajor and Devminor are only needed for special devices. + + // In FreeBSD, RDev for regular files is -1 (unless overridden by FS): + // https://cgit.freebsd.org/src/tree/sys/kern/vfs_default.c?h=stable/13#n1531 + // (NODEV is -1: https://cgit.freebsd.org/src/tree/sys/sys/param.h?h=stable/13#n241). + + // ZFS in particular does not override the default: + // https://cgit.freebsd.org/src/tree/sys/contrib/openzfs/module/os/freebsd/zfs/zfs_vnops_os.c?h=stable/13#n2027 + + // Since `Stat_t.Rdev` is uint64, the cast turns -1 into (2^64 - 1). + // Such large values cannot be encoded in a tar header. + if runtime.GOOS == "freebsd" && hdr.Typeflag != tar.TypeBlock && hdr.Typeflag != tar.TypeChar { + return nil + } + if s.Mode&unix.S_IFBLK != 0 || s.Mode&unix.S_IFCHR != 0 { hdr.Devmajor = int64(unix.Major(uint64(s.Rdev))) diff --git a/vendor/github.com/containerd/containerd/archive/time.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/time.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/time.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/time.go diff --git a/vendor/github.com/containerd/containerd/archive/time_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/time_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/time_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/time_unix.go diff --git a/vendor/github.com/containerd/containerd/archive/time_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/archive/time_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/archive/time_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/archive/time_windows.go diff --git a/vendor/github.com/containerd/containerd/pkg/cap/cap_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/cap/cap_linux.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/cap/cap_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/cap/cap_linux.go diff --git a/vendor/github.com/containerd/containerd/cio/io.go b/vendor/github.com/containerd/containerd/v2/pkg/cio/io.go similarity index 97% rename from vendor/github.com/containerd/containerd/cio/io.go rename to vendor/github.com/containerd/containerd/v2/pkg/cio/io.go index 8bd14c89c7..9e982cb0a9 100644 --- a/vendor/github.com/containerd/containerd/cio/io.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/cio/io.go @@ -26,7 +26,7 @@ import ( "strings" "sync" - "github.com/containerd/containerd/defaults" + "github.com/containerd/containerd/v2/defaults" ) var bufPool = sync.Pool{ @@ -71,7 +71,9 @@ type Creator func(id string) (IO, error) // will be sent only to the first reads type Attach func(*FIFOSet) (IO, error) -// FIFOSet is a set of file paths to FIFOs for a task's standard IO streams +// FIFOSet is a set of file paths to FIFOs for a task's standard IO streams, +// Although it supports streaming io other than FIFOs, +// we do not change the name "FIFOSet" because it is referenced in too many codes. type FIFOSet struct { Config close func() error diff --git a/vendor/github.com/containerd/containerd/cio/io_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/cio/io_unix.go similarity index 100% rename from vendor/github.com/containerd/containerd/cio/io_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/cio/io_unix.go diff --git a/vendor/github.com/containerd/containerd/cio/io_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/cio/io_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/cio/io_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/cio/io_windows.go diff --git a/vendor/github.com/containerd/containerd/v2/pkg/deprecation/deprecation.go b/vendor/github.com/containerd/containerd/v2/pkg/deprecation/deprecation.go new file mode 100644 index 0000000000..603bf41f06 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/deprecation/deprecation.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 deprecation + +type Warning string + +const ( + // Prefix is a standard prefix for all Warnings, used for filtering plugin Exports + Prefix = "io.containerd.deprecation/" + // PullSchema1Image is a warning for the use of schema 1 images + PullSchema1Image Warning = Prefix + "pull-schema-1-image" + // GoPluginLibrary is a warning for the use of dynamic library Go plugins + GoPluginLibrary Warning = Prefix + "go-plugin-library" + // CRIRegistryMirrors is a warning for the use of the `mirrors` property + CRIRegistryMirrors Warning = Prefix + "cri-registry-mirrors" + // CRIRegistryAuths is a warning for the use of the `auths` property + CRIRegistryAuths Warning = Prefix + "cri-registry-auths" + // CRIRegistryConfigs is a warning for the use of the `configs` property + CRIRegistryConfigs Warning = Prefix + "cri-registry-configs" + // OTLPTracingConfig is a warning for the use of the `otlp` property + TracingOTLPConfig Warning = Prefix + "tracing-processor-config" + // TracingServiceConfig is a warning for the use of the `tracing` property + TracingServiceConfig Warning = Prefix + "tracing-service-config" +) + +const ( + EnvPrefix = "CONTAINERD_ENABLE_DEPRECATED_" + EnvPullSchema1Image = EnvPrefix + "PULL_SCHEMA_1_IMAGE" +) + +var messages = map[Warning]string{ + PullSchema1Image: "Schema 1 images are deprecated since containerd v1.7, disabled in containerd v2.0, and will be removed in containerd v2.1. " + + `Since containerd v1.7.8, schema 1 images are identified by the "io.containerd.image/converted-docker-schema1" label.`, + GoPluginLibrary: "Dynamically-linked Go plugins as containerd runtimes are deprecated since containerd v2.0 and removed in containerd v2.1.", + CRIRegistryMirrors: "The `mirrors` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.1." + + "Use `config_path` instead.", + CRIRegistryAuths: "The `auths` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.3 and will be removed in containerd v2.1." + + "Use `ImagePullSecrets` instead.", + CRIRegistryConfigs: "The `configs` property of `[plugins.\"io.containerd.grpc.v1.cri\".registry]` is deprecated since containerd v1.5 and will be removed in containerd v2.1." + + "Use `config_path` instead.", + + TracingOTLPConfig: "The `otlp` property of `[plugins.\"io.containerd.tracing.processor.v1\".otlp]` is deprecated since containerd v1.6 and will be removed in containerd v2.0." + + "Use OTLP environment variables instead: https://opentelemetry.io/docs/specs/otel/protocol/exporter/", + TracingServiceConfig: "The `tracing` property of `[plugins.\"io.containerd.internal.v1\".tracing]` is deprecated since containerd v1.6 and will be removed in containerd v2.0." + + "Use OTEL environment variables instead: https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/", +} + +// Valid checks whether a given Warning is valid +func Valid(id Warning) bool { + _, ok := messages[id] + return ok +} + +// Message returns the human-readable message for a given Warning +func Message(id Warning) (string, bool) { + msg, ok := messages[id] + return msg, ok +} diff --git a/vendor/github.com/containerd/containerd/pkg/dialer/dialer.go b/vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer.go similarity index 91% rename from vendor/github.com/containerd/containerd/pkg/dialer/dialer.go rename to vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer.go index 74c303b944..125edf6922 100644 --- a/vendor/github.com/containerd/containerd/pkg/dialer/dialer.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer.go @@ -36,10 +36,6 @@ func ContextDialer(ctx context.Context, address string) (net.Conn, error) { return timeoutDialer(address, 0) } -// Dialer returns a GRPC net.Conn connected to the provided address -// Deprecated: use ContextDialer and grpc.WithContextDialer. -var Dialer = timeoutDialer - func timeoutDialer(address string, timeout time.Duration) (net.Conn, error) { var ( stopC = make(chan struct{}) diff --git a/vendor/github.com/containerd/containerd/pkg/dialer/dialer_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer_unix.go similarity index 84% rename from vendor/github.com/containerd/containerd/pkg/dialer/dialer_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer_unix.go index 798566bc5d..1c58d16b6e 100644 --- a/vendor/github.com/containerd/containerd/pkg/dialer/dialer_unix.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer_unix.go @@ -19,9 +19,9 @@ package dialer import ( + "errors" "fmt" "net" - "os" "strings" "syscall" "time" @@ -34,16 +34,7 @@ func DialAddress(address string) string { } func isNoent(err error) bool { - if err != nil { - if nerr, ok := err.(*net.OpError); ok { - if serr, ok := nerr.Err.(*os.SyscallError); ok { - if serr.Err == syscall.ENOENT { - return true - } - } - } - } - return false + return errors.Is(err, syscall.ENOENT) } func dialer(address string, timeout time.Duration) (net.Conn, error) { diff --git a/vendor/github.com/containerd/containerd/pkg/dialer/dialer_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer_windows.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/dialer/dialer_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/dialer/dialer_windows.go diff --git a/vendor/github.com/containerd/containerd/pkg/epoch/context.go b/vendor/github.com/containerd/containerd/v2/pkg/epoch/context.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/epoch/context.go rename to vendor/github.com/containerd/containerd/v2/pkg/epoch/context.go diff --git a/vendor/github.com/containerd/containerd/pkg/epoch/epoch.go b/vendor/github.com/containerd/containerd/v2/pkg/epoch/epoch.go similarity index 70% rename from vendor/github.com/containerd/containerd/pkg/epoch/epoch.go rename to vendor/github.com/containerd/containerd/v2/pkg/epoch/epoch.go index 124e8edb50..2b6718fa62 100644 --- a/vendor/github.com/containerd/containerd/pkg/epoch/epoch.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/epoch/epoch.go @@ -22,8 +22,6 @@ import ( "os" "strconv" "time" - - "github.com/sirupsen/logrus" ) // SourceDateEpochEnv is the SOURCE_DATE_EPOCH env var. @@ -37,33 +35,33 @@ func SourceDateEpoch() (*time.Time, error) { if !ok || v == "" { return nil, nil // not an error } - i64, err := strconv.ParseInt(v, 10, 64) + t, err := ParseSourceDateEpoch(v) if err != nil { - return nil, fmt.Errorf("invalid %s value %q: %w", SourceDateEpochEnv, v, err) + return nil, fmt.Errorf("invalid %s value: %w", SourceDateEpochEnv, err) + } + return t, nil +} + +// ParseSourceDateEpoch parses the given source date epoch, as *time.Time. +// It returns an error if sourceDateEpoch is empty or not well-formatted. +func ParseSourceDateEpoch(sourceDateEpoch string) (*time.Time, error) { + if sourceDateEpoch == "" { + return nil, fmt.Errorf("value is empty") + } + i64, err := strconv.ParseInt(sourceDateEpoch, 10, 64) + if err != nil { + return nil, fmt.Errorf("invalid value: %w", err) } unix := time.Unix(i64, 0).UTC() return &unix, nil } -// SourceDateEpochOrNow returns the SOURCE_DATE_EPOCH time if available, -// otherwise returns the current time. -func SourceDateEpochOrNow() time.Time { - epoch, err := SourceDateEpoch() - if err != nil { - logrus.WithError(err).Warnf("Invalid %s", SourceDateEpochEnv) - } - if epoch != nil { - return *epoch - } - return time.Now().UTC() -} - // SetSourceDateEpoch sets the SOURCE_DATE_EPOCH env var. func SetSourceDateEpoch(tm time.Time) { - os.Setenv(SourceDateEpochEnv, fmt.Sprintf("%d", tm.Unix())) + _ = os.Setenv(SourceDateEpochEnv, fmt.Sprintf("%d", tm.Unix())) } // UnsetSourceDateEpoch unsets the SOURCE_DATE_EPOCH env var. func UnsetSourceDateEpoch() { - os.Unsetenv(SourceDateEpochEnv) + _ = os.Unsetenv(SourceDateEpochEnv) } diff --git a/vendor/github.com/containerd/containerd/filters/adaptor.go b/vendor/github.com/containerd/containerd/v2/pkg/filters/adaptor.go similarity index 100% rename from vendor/github.com/containerd/containerd/filters/adaptor.go rename to vendor/github.com/containerd/containerd/v2/pkg/filters/adaptor.go diff --git a/vendor/github.com/containerd/containerd/filters/filter.go b/vendor/github.com/containerd/containerd/v2/pkg/filters/filter.go similarity index 100% rename from vendor/github.com/containerd/containerd/filters/filter.go rename to vendor/github.com/containerd/containerd/v2/pkg/filters/filter.go diff --git a/vendor/github.com/containerd/containerd/filters/parser.go b/vendor/github.com/containerd/containerd/v2/pkg/filters/parser.go similarity index 91% rename from vendor/github.com/containerd/containerd/filters/parser.go rename to vendor/github.com/containerd/containerd/v2/pkg/filters/parser.go index 790597aaf2..e86ed8eb46 100644 --- a/vendor/github.com/containerd/containerd/filters/parser.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/filters/parser.go @@ -20,7 +20,7 @@ import ( "fmt" "io" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ) /* @@ -121,7 +121,7 @@ loop: case tokenEOF: break loop default: - return nil, p.mkerrf(p.scanner.ppos, "unexpected input: %v", string(tok)) + return nil, p.mkerr(p.scanner.ppos, "unexpected input: %v", string(tok)) } } @@ -208,7 +208,7 @@ func (p *parser) field() (string, error) { case tokenQuoted: return p.unquote(pos, s, false) case tokenIllegal: - return "", p.mkerr(pos, p.scanner.err) + return "", p.mkerr(pos, "%s", p.scanner.err) } return "", p.mkerr(pos, "expected field or quoted") @@ -226,10 +226,10 @@ func (p *parser) operator() (operator, error) { case "~=": return operatorMatches, nil default: - return 0, p.mkerrf(pos, "unsupported operator %q", s) + return 0, p.mkerr(pos, "unsupported operator %q", s) } case tokenIllegal: - return 0, p.mkerr(pos, p.scanner.err) + return 0, p.mkerr(pos, "%s", p.scanner.err) } return 0, p.mkerr(pos, `expected an operator ("=="|"!="|"~=")`) @@ -244,7 +244,7 @@ func (p *parser) value(allowAltQuotes bool) (string, error) { case tokenQuoted: return p.unquote(pos, s, allowAltQuotes) case tokenIllegal: - return "", p.mkerr(pos, p.scanner.err) + return "", p.mkerr(pos, "%s", p.scanner.err) } return "", p.mkerr(pos, "expected value or quoted") @@ -257,7 +257,7 @@ func (p *parser) unquote(pos int, s string, allowAlts bool) (string, error) { uq, err := unquote(s) if err != nil { - return "", p.mkerrf(pos, "unquoting failed: %v", err) + return "", p.mkerr(pos, "unquoting failed: %v", err) } return uq, nil @@ -281,14 +281,10 @@ func (pe parseError) Error() string { return fmt.Sprintf("[%s]: %v", pe.input, pe.msg) } -func (p *parser) mkerrf(pos int, format string, args ...interface{}) error { - return p.mkerr(pos, fmt.Sprintf(format, args...)) -} - -func (p *parser) mkerr(pos int, msg string) error { +func (p *parser) mkerr(pos int, format string, args ...interface{}) error { return fmt.Errorf("parse error: %w", parseError{ input: p.input, pos: pos, - msg: msg, + msg: fmt.Sprintf(format, args...), }) } diff --git a/vendor/github.com/containerd/containerd/filters/quote.go b/vendor/github.com/containerd/containerd/v2/pkg/filters/quote.go similarity index 100% rename from vendor/github.com/containerd/containerd/filters/quote.go rename to vendor/github.com/containerd/containerd/v2/pkg/filters/quote.go diff --git a/vendor/github.com/containerd/containerd/filters/scanner.go b/vendor/github.com/containerd/containerd/v2/pkg/filters/scanner.go similarity index 100% rename from vendor/github.com/containerd/containerd/filters/scanner.go rename to vendor/github.com/containerd/containerd/v2/pkg/filters/scanner.go diff --git a/vendor/github.com/containerd/containerd/gc/gc.go b/vendor/github.com/containerd/containerd/v2/pkg/gc/gc.go similarity index 97% rename from vendor/github.com/containerd/containerd/gc/gc.go rename to vendor/github.com/containerd/containerd/v2/pkg/gc/gc.go index 079a6eae97..67d9a0476c 100644 --- a/vendor/github.com/containerd/containerd/gc/gc.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/gc/gc.go @@ -69,12 +69,14 @@ func Tricolor(roots []Node, refs func(ref Node) ([]Node, error)) (map[Node]struc ) grays = append(grays, roots...) + for _, root := range roots { + seen[root] = struct{}{} // pre-mark this as not-white + } for len(grays) > 0 { // Pick any gray object id := grays[len(grays)-1] // effectively "depth first" because first element grays = grays[:len(grays)-1] - seen[id] = struct{}{} // post-mark this as not-white rs, err := refs(id) if err != nil { return nil, err @@ -84,6 +86,7 @@ func Tricolor(roots []Node, refs func(ref Node) ([]Node, error)) (map[Node]struc for _, target := range rs { if _, ok := seen[target]; !ok { grays = append(grays, target) + seen[target] = struct{}{} } } diff --git a/vendor/github.com/containerd/containerd/identifiers/validate.go b/vendor/github.com/containerd/containerd/v2/pkg/identifiers/validate.go similarity index 98% rename from vendor/github.com/containerd/containerd/identifiers/validate.go rename to vendor/github.com/containerd/containerd/v2/pkg/identifiers/validate.go index cbd3a52ba9..0acbf3fc4b 100644 --- a/vendor/github.com/containerd/containerd/identifiers/validate.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/identifiers/validate.go @@ -28,7 +28,7 @@ import ( "fmt" "regexp" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ) const ( diff --git a/vendor/github.com/containerd/containerd/contrib/seccomp/kernelversion/kernel_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/kernelversion/kernel_linux.go similarity index 99% rename from vendor/github.com/containerd/containerd/contrib/seccomp/kernelversion/kernel_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/kernelversion/kernel_linux.go index ab288fbb8a..a8cec6481f 100644 --- a/vendor/github.com/containerd/containerd/contrib/seccomp/kernelversion/kernel_linux.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/kernelversion/kernel_linux.go @@ -12,7 +12,9 @@ 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. +*/ +/* File copied and customized based on https://github.com/moby/moby/tree/v20.10.14/profiles/seccomp/kernel_linux.go */ diff --git a/vendor/github.com/containerd/containerd/labels/labels.go b/vendor/github.com/containerd/containerd/v2/pkg/labels/labels.go similarity index 100% rename from vendor/github.com/containerd/containerd/labels/labels.go rename to vendor/github.com/containerd/containerd/v2/pkg/labels/labels.go diff --git a/vendor/github.com/containerd/containerd/labels/validate.go b/vendor/github.com/containerd/containerd/v2/pkg/labels/validate.go similarity index 96% rename from vendor/github.com/containerd/containerd/labels/validate.go rename to vendor/github.com/containerd/containerd/v2/pkg/labels/validate.go index f83b5dde29..6f23cdd7c6 100644 --- a/vendor/github.com/containerd/containerd/labels/validate.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/labels/validate.go @@ -19,7 +19,7 @@ package labels import ( "fmt" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ) const ( diff --git a/vendor/github.com/containerd/containerd/namespaces/context.go b/vendor/github.com/containerd/containerd/v2/pkg/namespaces/context.go similarity index 96% rename from vendor/github.com/containerd/containerd/namespaces/context.go rename to vendor/github.com/containerd/containerd/v2/pkg/namespaces/context.go index e5e23fe430..dbbc28615d 100644 --- a/vendor/github.com/containerd/containerd/namespaces/context.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/namespaces/context.go @@ -21,8 +21,8 @@ import ( "fmt" "os" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/identifiers" + "github.com/containerd/containerd/v2/pkg/identifiers" + "github.com/containerd/errdefs" ) const ( diff --git a/vendor/github.com/containerd/containerd/namespaces/grpc.go b/vendor/github.com/containerd/containerd/v2/pkg/namespaces/grpc.go similarity index 100% rename from vendor/github.com/containerd/containerd/namespaces/grpc.go rename to vendor/github.com/containerd/containerd/v2/pkg/namespaces/grpc.go diff --git a/vendor/github.com/containerd/containerd/namespaces/store.go b/vendor/github.com/containerd/containerd/v2/pkg/namespaces/store.go similarity index 100% rename from vendor/github.com/containerd/containerd/namespaces/store.go rename to vendor/github.com/containerd/containerd/v2/pkg/namespaces/store.go diff --git a/vendor/github.com/containerd/containerd/namespaces/ttrpc.go b/vendor/github.com/containerd/containerd/v2/pkg/namespaces/ttrpc.go similarity index 100% rename from vendor/github.com/containerd/containerd/namespaces/ttrpc.go rename to vendor/github.com/containerd/containerd/v2/pkg/namespaces/ttrpc.go diff --git a/vendor/github.com/containerd/containerd/oci/client.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/client.go similarity index 91% rename from vendor/github.com/containerd/containerd/oci/client.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/client.go index 9923101bfa..b16474cd88 100644 --- a/vendor/github.com/containerd/containerd/oci/client.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/client.go @@ -19,8 +19,8 @@ package oci import ( "context" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/snapshots" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/containerd/containerd/oci/mounts.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/mounts.go similarity index 100% rename from vendor/github.com/containerd/containerd/oci/mounts.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/mounts.go diff --git a/vendor/github.com/containerd/containerd/oci/mounts_freebsd.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/mounts_freebsd.go similarity index 100% rename from vendor/github.com/containerd/containerd/oci/mounts_freebsd.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/mounts_freebsd.go diff --git a/vendor/github.com/containerd/containerd/oci/spec.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec.go similarity index 84% rename from vendor/github.com/containerd/containerd/oci/spec.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec.go index 86fef42b2d..06a97580ad 100644 --- a/vendor/github.com/containerd/containerd/oci/spec.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec.go @@ -23,10 +23,13 @@ import ( "path/filepath" "runtime" + "github.com/opencontainers/go-digest" + ocispec "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runtime-spec/specs-go" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/api/types" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/platforms" ) @@ -64,7 +67,7 @@ func ReadSpec(path string) (*Spec, error) { // GenerateSpec will generate a default spec from the provided image // for use as a containerd container func GenerateSpec(ctx context.Context, client Client, c *containers.Container, opts ...SpecOpts) (*Spec, error) { - return GenerateSpecWithPlatform(ctx, client, platforms.Format(platforms.DefaultSpec()), c, opts...) // For 1.7 continue using the old format without os-version included. + return GenerateSpecWithPlatform(ctx, client, platforms.DefaultString(), c, opts...) } // GenerateSpecWithPlatform will generate a default spec from the provided image @@ -239,3 +242,25 @@ func populateDefaultDarwinSpec(s *Spec) error { } return nil } + +// DescriptorFromProto converts containerds protobuf [types.Descriptor] +// to the OCI image specs [ocispec.Descriptor]. +func DescriptorFromProto(d *types.Descriptor) ocispec.Descriptor { + return ocispec.Descriptor{ + MediaType: d.MediaType, + Digest: digest.Digest(d.Digest), + Size: d.Size, + Annotations: d.Annotations, + } +} + +// DescriptorToProto converts the OCI image specs [ocispec.Descriptor] +// to containerds protobuf [types.Descriptor]. +func DescriptorToProto(d ocispec.Descriptor) *types.Descriptor { + return &types.Descriptor{ + MediaType: d.MediaType, + Digest: d.Digest.String(), + Size: d.Size, + Annotations: d.Annotations, + } +} diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts.go similarity index 95% rename from vendor/github.com/containerd/containerd/oci/spec_opts.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts.go index f1422d5052..5101c63bb6 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts.go @@ -28,16 +28,18 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/containerd/continuity/fs" + "github.com/containerd/log" "github.com/containerd/platforms" "github.com/moby/sys/user" v1 "github.com/opencontainers/image-spec/specs-go/v1" "github.com/opencontainers/runtime-spec/specs-go" + "tags.cncf.io/container-device-interface/pkg/cdi" ) // SpecOpts sets spec specific information to a newly generated OCI spec @@ -138,7 +140,7 @@ func ensureAdditionalGids(s *Spec) { // Use as the first option to clear the spec, then apply options afterwards. func WithDefaultSpec() SpecOpts { return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { - return generateDefaultSpecWithPlatform(ctx, platforms.Format(platforms.DefaultSpec()), c.ID, s) // For 1.7 continue using the old format without os-version included. + return generateDefaultSpecWithPlatform(ctx, platforms.DefaultString(), c.ID, s) } } @@ -367,27 +369,25 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts { if err != nil { return err } + if !images.IsConfigType(ic.MediaType) { + return fmt.Errorf("unknown image config media type %s", ic.MediaType) + } + var ( imageConfigBytes []byte ociimage v1.Image config v1.ImageConfig ) - switch ic.MediaType { - case v1.MediaTypeImageConfig, images.MediaTypeDockerSchema2Config: - var err error - imageConfigBytes, err = content.ReadBlob(ctx, image.ContentStore(), ic) - if err != nil { - return err - } - - if err := json.Unmarshal(imageConfigBytes, &ociimage); err != nil { - return err - } - config = ociimage.Config - default: - return fmt.Errorf("unknown image config media type %s", ic.MediaType) + imageConfigBytes, err = content.ReadBlob(ctx, image.ContentStore(), ic) + if err != nil { + return err } + if err = json.Unmarshal(imageConfigBytes, &ociimage); err != nil { + return err + } + config = ociimage.Config + appendOSMounts(s, ociimage.OS) setProcess(s) if s.Linux != nil { @@ -411,7 +411,7 @@ func WithImageConfigArgs(image Image, args []string) SpecOpts { if err := WithUser(config.User)(ctx, client, c, s); err != nil { return err } - return WithAdditionalGIDs(fmt.Sprintf("%d", s.Process.User.UID))(ctx, client, c, s) + return WithAdditionalGIDs(strconv.FormatInt(int64(s.Process.User.UID), 10))(ctx, client, c, s) } // we should query the image's /etc/group for additional GIDs // even if there is no specified user in the image config @@ -1098,9 +1098,9 @@ func getSupplementalGroupsFromPath(root string, filter func(user.Group) bool) ([ // if there are no additional groups; just return an empty set return []uint32{}, nil } - addlGids := []uint32{} - for _, grp := range groups { - addlGids = append(addlGids, uint32(grp.Gid)) + addlGids := make([]uint32, len(groups)) + for i, grp := range groups { + addlGids[i] = uint32(grp.Gid) } return addlGids, nil } @@ -1538,6 +1538,15 @@ func WithCPUCFS(quota int64, period uint64) SpecOpts { } } +// WithCPUBurst sets the container's cpu burst +func WithCPUBurst(burst uint64) SpecOpts { + return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { + setCPU(s) + s.Linux.Resources.CPU.Burst = &burst + return nil + } +} + // WithCPURT sets the container's realtime scheduling (RT) runtime and period. func WithCPURT(runtime int64, period uint64) SpecOpts { return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { @@ -1634,3 +1643,31 @@ func WithWindowsNetworkNamespace(ns string) SpecOpts { return nil } } + +// WithCDIDevices injects the requested CDI devices into the OCI specification. +func WithCDIDevices(devices ...string) SpecOpts { + return func(ctx context.Context, _ Client, c *containers.Container, s *Spec) error { + if len(devices) == 0 { + return nil + } + + if err := cdi.Refresh(); err != nil { + // We don't consider registry refresh failure a fatal error. + // For instance, a dynamically generated invalid CDI Spec file for + // any particular vendor shouldn't prevent injection of devices of + // different vendors. CDI itself knows better and it will fail the + // injection if necessary. + log.G(ctx).Warnf("CDI registry refresh failed: %v", err) + } + + if _, err := cdi.InjectDevices(s, devices...); err != nil { + return fmt.Errorf("CDI device injection failed: %w", err) + } + + // One crucial thing to keep in mind is that CDI device injection + // might add OCI Spec environment variables, hooks, and mounts as + // well. Therefore it is important that none of the corresponding + // OCI Spec fields are reset up in the call stack once we return. + return nil + } +} diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_linux.go similarity index 96% rename from vendor/github.com/containerd/containerd/oci/spec_opts_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_linux.go index bccea766aa..d3f4105b41 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_linux.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_linux.go @@ -19,8 +19,8 @@ package oci import ( "context" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/cap" specs "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_nonlinux.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_nonlinux.go similarity index 95% rename from vendor/github.com/containerd/containerd/oci/spec_opts_nonlinux.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_nonlinux.go index b2f796f361..3a7a9690d6 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_nonlinux.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_nonlinux.go @@ -21,7 +21,7 @@ package oci import ( "context" - "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/v2/core/containers" ) // WithAllCurrentCapabilities propagates the effective capabilities of the caller process to the container process. diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_nonwindows.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_nonwindows.go similarity index 94% rename from vendor/github.com/containerd/containerd/oci/spec_opts_nonwindows.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_nonwindows.go index 06bcc3041c..9cb9e4645c 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_nonwindows.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_nonwindows.go @@ -21,7 +21,7 @@ package oci import ( "context" - "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/v2/core/containers" ) // WithDefaultPathEnv sets the $PATH environment variable to the diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_unix.go similarity index 96% rename from vendor/github.com/containerd/containerd/oci/spec_opts_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_unix.go index f4135285cc..26e575ff28 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_unix.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_unix.go @@ -21,7 +21,7 @@ package oci import ( "context" - "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/v2/core/containers" ) // WithHostDevices adds all the hosts device nodes to the container's spec diff --git a/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_windows.go similarity index 97% rename from vendor/github.com/containerd/containerd/oci/spec_opts_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_windows.go index 7d49d27407..658c10b204 100644 --- a/vendor/github.com/containerd/containerd/oci/spec_opts_windows.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/spec_opts_windows.go @@ -24,7 +24,7 @@ import ( "github.com/opencontainers/runtime-spec/specs-go" "golang.org/x/sys/windows" - "github.com/containerd/containerd/containers" + "github.com/containerd/containerd/v2/core/containers" ) func escapeAndCombineArgs(args []string) string { diff --git a/vendor/github.com/containerd/containerd/oci/utils_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/oci/utils_unix.go similarity index 94% rename from vendor/github.com/containerd/containerd/oci/utils_unix.go rename to vendor/github.com/containerd/containerd/v2/pkg/oci/utils_unix.go index 602bbed148..37a32f53f9 100644 --- a/vendor/github.com/containerd/containerd/oci/utils_unix.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/oci/utils_unix.go @@ -30,6 +30,7 @@ import ( ) // ErrNotADevice denotes that a file is not a valid linux device. +// When checking this error, use errors.Is(err, oci.ErrNotADevice) var ErrNotADevice = errors.New("not a device node") // Testing dependencies @@ -53,6 +54,10 @@ func getDevices(path, containerPath string) ([]specs.LinuxDevice, error) { if !stat.IsDir() { dev, err := DeviceFromPath(path) if err != nil { + // wrap error with detailed path and container path when it is ErrNotADevice + if err == ErrNotADevice { + return nil, fmt.Errorf("get device path: %q containerPath: %q error: %w", path, containerPath, err) + } return nil, err } if containerPath != "" { diff --git a/vendor/github.com/containerd/containerd/protobuf/compare.go b/vendor/github.com/containerd/containerd/v2/pkg/protobuf/compare.go similarity index 100% rename from vendor/github.com/containerd/containerd/protobuf/compare.go rename to vendor/github.com/containerd/containerd/v2/pkg/protobuf/compare.go diff --git a/vendor/github.com/containerd/containerd/protobuf/proto/proto.go b/vendor/github.com/containerd/containerd/v2/pkg/protobuf/proto/proto.go similarity index 93% rename from vendor/github.com/containerd/containerd/protobuf/proto/proto.go rename to vendor/github.com/containerd/containerd/v2/pkg/protobuf/proto/proto.go index 6c5e7b75e3..36902b1aa5 100644 --- a/vendor/github.com/containerd/containerd/protobuf/proto/proto.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/protobuf/proto/proto.go @@ -14,7 +14,7 @@ limitations under the License. */ -// Package proto provides convinient aliases that make google.golang.org/protobuf migration easier. +// Package proto provides convenient aliases that make google.golang.org/protobuf migration easier. package proto import ( diff --git a/vendor/github.com/containerd/containerd/protobuf/timestamp.go b/vendor/github.com/containerd/containerd/v2/pkg/protobuf/timestamp.go similarity index 100% rename from vendor/github.com/containerd/containerd/protobuf/timestamp.go rename to vendor/github.com/containerd/containerd/v2/pkg/protobuf/timestamp.go diff --git a/vendor/github.com/containerd/containerd/protobuf/types/types.go b/vendor/github.com/containerd/containerd/v2/pkg/protobuf/types/types.go similarity index 86% rename from vendor/github.com/containerd/containerd/protobuf/types/types.go rename to vendor/github.com/containerd/containerd/v2/pkg/protobuf/types/types.go index 1a920a2f98..dd0b0299b6 100644 --- a/vendor/github.com/containerd/containerd/protobuf/types/types.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/protobuf/types/types.go @@ -14,13 +14,13 @@ limitations under the License. */ -// Package types provides convinient aliases that make google.golang.org/protobuf migration easier. +// Package types provides convenient aliases that make google.golang.org/protobuf migration easier. package types import ( - "google.golang.org/genproto/protobuf/field_mask" "google.golang.org/protobuf/types/known/anypb" "google.golang.org/protobuf/types/known/emptypb" + field_mask "google.golang.org/protobuf/types/known/fieldmaskpb" ) type Empty = emptypb.Empty diff --git a/vendor/github.com/containerd/containerd/reference/reference.go b/vendor/github.com/containerd/containerd/v2/pkg/reference/reference.go similarity index 83% rename from vendor/github.com/containerd/containerd/reference/reference.go rename to vendor/github.com/containerd/containerd/v2/pkg/reference/reference.go index 9329a9aab8..d983c4e135 100644 --- a/vendor/github.com/containerd/containerd/reference/reference.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/reference/reference.go @@ -154,26 +154,3 @@ func (r Spec) String() string { return r.Locator + ":" + r.Object } - -// SplitObject provides two parts of the object spec, delimited by an "@" -// symbol. It does not perform any validation on correctness of the values -// returned, and it's the callers' responsibility to validate the result. -// -// If an "@" delimiter is found, it returns the part *including* the "@" -// delimiter as "tag", and the part after the "@" as digest. -// -// The example below produces "docker.io/library/ubuntu:latest@" and -// "sha256:deadbeef"; -// -// t, d := SplitObject("docker.io/library/ubuntu:latest@sha256:deadbeef") -// fmt.Println(t) // docker.io/library/ubuntu:latest@ -// fmt.Println(d) // sha256:deadbeef -// -// Deprecated: use [Parse] and [Spec.Digest] instead. -func SplitObject(obj string) (tag string, dgst digest.Digest) { - if i := strings.Index(obj, "@"); i >= 0 { - // Offset by one so preserve the "@" in the tag returned. - return obj[:i+1], digest.Digest(obj[i+1:]) - } - return obj, "" -} diff --git a/vendor/github.com/containerd/containerd/rootfs/apply.go b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/apply.go similarity index 97% rename from vendor/github.com/containerd/containerd/rootfs/apply.go rename to vendor/github.com/containerd/containerd/v2/pkg/rootfs/apply.go index b22011e87e..2955d549f4 100644 --- a/vendor/github.com/containerd/containerd/rootfs/apply.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/apply.go @@ -23,15 +23,14 @@ import ( "fmt" "time" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/opencontainers/go-digest" "github.com/opencontainers/image-spec/identity" ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" ) // Layer represents the descriptors for a layer diff. These descriptions diff --git a/vendor/github.com/containerd/containerd/rootfs/diff.go b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/diff.go similarity index 90% rename from vendor/github.com/containerd/containerd/rootfs/diff.go rename to vendor/github.com/containerd/containerd/v2/pkg/rootfs/diff.go index da9dbe2752..8659670bf9 100644 --- a/vendor/github.com/containerd/containerd/rootfs/diff.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/diff.go @@ -20,10 +20,10 @@ import ( "context" "fmt" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/pkg/cleanup" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/internal/cleanup" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/containerd/containerd/rootfs/init.go b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/init.go similarity index 96% rename from vendor/github.com/containerd/containerd/rootfs/init.go rename to vendor/github.com/containerd/containerd/v2/pkg/rootfs/init.go index e6866ace2b..a2bd4c5d98 100644 --- a/vendor/github.com/containerd/containerd/rootfs/init.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/init.go @@ -22,8 +22,8 @@ import ( "fmt" "os" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/containerd/log" digest "github.com/opencontainers/go-digest" ) diff --git a/vendor/github.com/containerd/containerd/rootfs/init_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/init_linux.go similarity index 100% rename from vendor/github.com/containerd/containerd/rootfs/init_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/rootfs/init_linux.go diff --git a/vendor/github.com/containerd/containerd/rootfs/init_other.go b/vendor/github.com/containerd/containerd/v2/pkg/rootfs/init_other.go similarity index 100% rename from vendor/github.com/containerd/containerd/rootfs/init_other.go rename to vendor/github.com/containerd/containerd/v2/pkg/rootfs/init_other.go diff --git a/vendor/github.com/containerd/containerd/pkg/seccomp/seccomp.go b/vendor/github.com/containerd/containerd/v2/pkg/seccomp/seccomp.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/seccomp/seccomp.go rename to vendor/github.com/containerd/containerd/v2/pkg/seccomp/seccomp.go diff --git a/vendor/github.com/containerd/containerd/pkg/seccomp/seccomp_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/seccomp/seccomp_linux.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/seccomp/seccomp_linux.go rename to vendor/github.com/containerd/containerd/v2/pkg/seccomp/seccomp_linux.go diff --git a/vendor/github.com/containerd/containerd/pkg/seccomp/seccomp_unsupported.go b/vendor/github.com/containerd/containerd/v2/pkg/seccomp/seccomp_unsupported.go similarity index 100% rename from vendor/github.com/containerd/containerd/pkg/seccomp/seccomp_unsupported.go rename to vendor/github.com/containerd/containerd/v2/pkg/seccomp/seccomp_unsupported.go diff --git a/vendor/github.com/containerd/containerd/pkg/snapshotters/annotations.go b/vendor/github.com/containerd/containerd/v2/pkg/snapshotters/annotations.go similarity index 95% rename from vendor/github.com/containerd/containerd/pkg/snapshotters/annotations.go rename to vendor/github.com/containerd/containerd/v2/pkg/snapshotters/annotations.go index 63476376c1..2e44b05fb3 100644 --- a/vendor/github.com/containerd/containerd/pkg/snapshotters/annotations.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/snapshotters/annotations.go @@ -19,8 +19,8 @@ package snapshotters import ( "context" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" "github.com/containerd/log" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) @@ -55,8 +55,7 @@ func AppendInfoHandlerWrapper(ref string) func(f images.Handler) images.Handler if err != nil { return nil, err } - switch desc.MediaType { - case ocispec.MediaTypeImageManifest, images.MediaTypeDockerSchema2Manifest: + if images.IsManifestType(desc.MediaType) { for i := range children { c := &children[i] if images.IsLayerType(c.MediaType) { diff --git a/vendor/github.com/containerd/containerd/archive/link_freebsd.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/eintr_unix.go similarity index 85% rename from vendor/github.com/containerd/containerd/archive/link_freebsd.go rename to vendor/github.com/containerd/containerd/v2/pkg/sys/eintr_unix.go index 2097db06bc..1106a5dbca 100644 --- a/vendor/github.com/containerd/containerd/archive/link_freebsd.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/eintr_unix.go @@ -1,3 +1,5 @@ +//go:build !windows + /* Copyright The containerd Authors. @@ -14,24 +16,9 @@ limitations under the License. */ -package archive +package sys -import ( - "os" - "syscall" - - "golang.org/x/sys/unix" -) - -func link(oldname, newname string) error { - e := ignoringEINTR(func() error { - return unix.Linkat(unix.AT_FDCWD, oldname, unix.AT_FDCWD, newname, 0) - }) - if e != nil { - return &os.LinkError{Op: "link", Old: oldname, New: newname, Err: e} - } - return nil -} +import "golang.org/x/sys/unix" // The following contents were copied from Go 1.18.2. // Use of this source code is governed by the following @@ -65,17 +52,17 @@ func link(oldname, newname string) error { // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// ignoringEINTR makes a function call and repeats it if it returns an +// IgnoringEINTR makes a function call and repeats it if it returns an // EINTR error. This appears to be required even though we install all // signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846. // Also #20400 and #36644 are issues in which a signal handler is // installed without setting SA_RESTART. None of these are the common case, // but there are enough of them that it seems that we can't avoid // an EINTR loop. -func ignoringEINTR(fn func() error) error { +func IgnoringEINTR(fn func() error) error { for { err := fn() - if err != syscall.EINTR { + if err != unix.EINTR { return err } } diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/filesys_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/filesys_unix.go new file mode 100644 index 0000000000..333e85ceb4 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/filesys_unix.go @@ -0,0 +1,26 @@ +//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 sys + +import "os" + +// MkdirAllWithACL is a wrapper for os.MkdirAll on Unix systems. +func MkdirAllWithACL(path string, perm os.FileMode) error { + return os.MkdirAll(path, perm) +} diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/filesys_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/filesys_windows.go new file mode 100644 index 0000000000..67fc4048c1 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/filesys_windows.go @@ -0,0 +1,151 @@ +/* + 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 sys + +import ( + "os" + "regexp" + "syscall" + "unsafe" + + "golang.org/x/sys/windows" +) + +// SddlAdministratorsLocalSystem is local administrators plus NT AUTHORITY\System. +const SddlAdministratorsLocalSystem = "D:P(A;OICI;GA;;;BA)(A;OICI;GA;;;SY)" + +// volumePath is a regular expression to check if a path is a Windows +// volume path (e.g., "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}" +// or "\\?\Volume{4c1b02c1-d990-11dc-99ae-806e6f6e6963}\"). +var volumePath = regexp.MustCompile(`^\\\\\?\\Volume{[a-z0-9-]+}\\?$`) + +// MkdirAllWithACL is a custom version of os.MkdirAll modified for use on Windows +// so that it is both volume path aware, and to create a directory +// an appropriate SDDL defined ACL for Builtin Administrators and Local System. +func MkdirAllWithACL(path string, _ os.FileMode) error { + sa, err := makeSecurityAttributes(SddlAdministratorsLocalSystem) + if err != nil { + return &os.PathError{Op: "mkdirall", Path: path, Err: err} + } + return mkdirall(path, sa) +} + +// MkdirAll is a custom version of os.MkdirAll that is volume path aware for +// Windows. It can be used as a drop-in replacement for os.MkdirAll. +func MkdirAll(path string, _ os.FileMode) error { + return mkdirall(path, nil) +} + +// mkdirall is a custom version of os.MkdirAll modified for use on Windows +// so that it is both volume path aware, and can create a directory with +// a DACL. +func mkdirall(path string, perm *windows.SecurityAttributes) error { + if volumePath.MatchString(path) { + return nil + } + + // The rest of this method is largely copied from os.MkdirAll and should be kept + // as-is to ensure compatibility. + + // Fast path: if we can tell whether path is a directory or file, stop with success or error. + dir, err := os.Stat(path) + if err == nil { + if dir.IsDir() { + return nil + } + return &os.PathError{Op: "mkdir", Path: path, Err: syscall.ENOTDIR} + } + + // Slow path: make sure parent exists and then call Mkdir for path. + i := len(path) + for i > 0 && os.IsPathSeparator(path[i-1]) { // Skip trailing path separator. + i-- + } + + j := i + for j > 0 && !os.IsPathSeparator(path[j-1]) { // Scan backward over element. + j-- + } + + if j > 1 { + // Create parent. + err = mkdirall(fixRootDirectory(path[:j-1]), perm) + if err != nil { + return err + } + } + + // Parent now exists; invoke Mkdir and use its result. + err = mkdirWithACL(path, perm) + if err != nil { + // Handle arguments like "foo/." by + // double-checking that directory doesn't exist. + dir, err1 := os.Lstat(path) + if err1 == nil && dir.IsDir() { + return nil + } + return err + } + return nil +} + +// mkdirWithACL creates a new directory. If there is an error, it will be of +// type *PathError. . +// +// This is a modified and combined version of os.Mkdir and windows.Mkdir +// in golang to cater for creating a directory am ACL permitting full +// access, with inheritance, to any subfolder/file for Built-in Administrators +// and Local System. +func mkdirWithACL(name string, sa *windows.SecurityAttributes) error { + if sa == nil { + return os.Mkdir(name, 0) + } + + namep, err := windows.UTF16PtrFromString(name) + if err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + + err = windows.CreateDirectory(namep, sa) + if err != nil { + return &os.PathError{Op: "mkdir", Path: name, Err: err} + } + return nil +} + +// fixRootDirectory fixes a reference to a drive's root directory to +// have the required trailing slash. +func fixRootDirectory(p string) string { + if len(p) == len(`\\?\c:`) { + if os.IsPathSeparator(p[0]) && os.IsPathSeparator(p[1]) && p[2] == '?' && os.IsPathSeparator(p[3]) && p[5] == ':' { + return p + `\` + } + } + return p +} + +func makeSecurityAttributes(sddl string) (*windows.SecurityAttributes, error) { + var sa windows.SecurityAttributes + sa.Length = uint32(unsafe.Sizeof(sa)) + sa.InheritHandle = 1 + var err error + sa.SecurityDescriptor, err = windows.SecurityDescriptorFromString(sddl) + if err != nil { + return nil, err + } + return &sa, nil +} diff --git a/vendor/github.com/containerd/platforms/platforms_windows.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/namespace_linux.go similarity index 51% rename from vendor/github.com/containerd/platforms/platforms_windows.go rename to vendor/github.com/containerd/containerd/v2/pkg/sys/namespace_linux.go index 950e2a2ddb..d2a898acc6 100644 --- a/vendor/github.com/containerd/platforms/platforms_windows.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/namespace_linux.go @@ -14,21 +14,25 @@ limitations under the License. */ -package platforms +package sys import ( - specs "github.com/opencontainers/image-spec/specs-go/v1" + "fmt" + "os" + "syscall" + + "golang.org/x/sys/unix" ) -// NewMatcher returns a Windows matcher that will match on osVersionPrefix if -// the platform is Windows otherwise use the default matcher -func newDefaultMatcher(platform specs.Platform) Matcher { - prefix := prefix(platform.OSVersion) - return windowsmatcher{ - Platform: platform, - osVersionPrefix: prefix, - defaultMatcher: &matcher{ - Platform: Normalize(platform), - }, +// GetUsernsForNamespace returns a file descriptor that refers to the owning +// user namespace for the namespace referred to by fd. +// +// REF: https://man7.org/linux/man-pages/man2/ioctl_ns.2.html +func GetUsernsForNamespace(fd uintptr) (*os.File, error) { + fd, _, errno := unix.Syscall(syscall.SYS_IOCTL, fd, uintptr(unix.NS_GET_USERNS), 0) + if errno != 0 { + return nil, fmt.Errorf("failed to get user namespace fd: %w", errno) } + + return os.NewFile(fd, fmt.Sprintf("/proc/%d/fd/%d", os.Getpid(), fd)), nil } diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/oom_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/oom_linux.go new file mode 100644 index 0000000000..01ebbebb59 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/oom_linux.go @@ -0,0 +1,82 @@ +/* + 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 sys + +import ( + "fmt" + "os" + "strconv" + "strings" + + "github.com/moby/sys/userns" + "golang.org/x/sys/unix" +) + +const ( + // OOMScoreAdjMin is from OOM_SCORE_ADJ_MIN https://github.com/torvalds/linux/blob/v5.10/include/uapi/linux/oom.h#L9 + OOMScoreAdjMin = -1000 + // OOMScoreAdjMax is from OOM_SCORE_ADJ_MAX https://github.com/torvalds/linux/blob/v5.10/include/uapi/linux/oom.h#L10 + OOMScoreAdjMax = 1000 +) + +// AdjustOOMScore sets the oom score for the provided pid. If the provided score +// is out of range (-1000 - 1000), it is clipped to the min/max value. +func AdjustOOMScore(pid, score int) error { + if score > OOMScoreAdjMax { + score = OOMScoreAdjMax + } else if score < OOMScoreAdjMin { + score = OOMScoreAdjMin + } + return SetOOMScore(pid, score) +} + +// SetOOMScore sets the oom score for the provided pid +func SetOOMScore(pid, score int) error { + if score > OOMScoreAdjMax || score < OOMScoreAdjMin { + return fmt.Errorf("value out of range (%d): OOM score must be between %d and %d", score, OOMScoreAdjMin, OOMScoreAdjMax) + } + path := fmt.Sprintf("/proc/%d/oom_score_adj", pid) + f, err := os.OpenFile(path, os.O_WRONLY, 0) + if err != nil { + return err + } + defer f.Close() + if _, err = f.WriteString(strconv.Itoa(score)); err != nil { + if os.IsPermission(err) && (!runningPrivileged() || userns.RunningInUserNS()) { + return nil + } + return err + } + return nil +} + +// GetOOMScoreAdj gets the oom score for a process. It returns 0 (zero) if either +// no oom score is set, or a sore is set to 0. +func GetOOMScoreAdj(pid int) (int, error) { + path := fmt.Sprintf("/proc/%d/oom_score_adj", pid) + data, err := os.ReadFile(path) + if err != nil { + return 0, err + } + return strconv.Atoi(strings.TrimSpace(string(data))) +} + +// runningPrivileged returns true if the effective user ID of the +// calling process is 0 +func runningPrivileged() bool { + return unix.Geteuid() == 0 +} diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/oom_unsupported.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/oom_unsupported.go new file mode 100644 index 0000000000..f579774663 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/oom_unsupported.go @@ -0,0 +1,48 @@ +//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 sys + +const ( + // OOMScoreMaxKillable is not implemented on non Linux + OOMScoreMaxKillable = 0 + // OOMScoreAdjMax is not implemented on non Linux + OOMScoreAdjMax = 0 +) + +// AdjustOOMScore sets the oom score for the provided pid. If the provided score +// is out of range (-1000 - 1000), it is clipped to the min/max value. +// +// Not implemented on Windows +func AdjustOOMScore(pid, score int) error { + return nil +} + +// SetOOMScore sets the oom score for the process +// +// Not implemented on Windows +func SetOOMScore(pid, score int) error { + return nil +} + +// GetOOMScoreAdj gets the oom score for a process +// +// Not implemented on Windows +func GetOOMScoreAdj(pid int) (int, error) { + return 0, nil +} diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/pidfd_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/pidfd_linux.go new file mode 100644 index 0000000000..b6f82d793e --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/pidfd_linux.go @@ -0,0 +1,85 @@ +/* + 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 sys + +import ( + "context" + "errors" + "fmt" + "os" + "sync" + + "github.com/containerd/log" + "golang.org/x/sys/unix" +) + +var ( + pidfdSupported bool + pidfdSupportedOnce sync.Once +) + +// SupportsPidFD returns true if current kernel supports pidfd. +func SupportsPidFD() bool { + pidfdSupportedOnce.Do(func() { + logger := log.G(context.Background()) + + if err := checkPidFD(); err != nil { + logger.WithError(err).Error("failed to ensure the kernel supports pidfd") + + pidfdSupported = false + return + } + pidfdSupported = true + }) + return pidfdSupported +} + +func checkPidFD() error { + // Linux kernel supports pidfd_open(2) since v5.3. + // + // https://man7.org/linux/man-pages/man2/pidfd_open.2.html + pidfd, err := unix.PidfdOpen(os.Getpid(), 0) + if err != nil { + return fmt.Errorf("failed to invoke pidfd_open: %w", err) + } + defer unix.Close(pidfd) + + // Linux kernel supports pidfd_send_signal(2) since v5.1. + // + // https://man7.org/linux/man-pages/man2/pidfd_send_signal.2.html + if err := unix.PidfdSendSignal(pidfd, 0, nil, 0); err != nil { + return fmt.Errorf("failed to invoke pidfd_send_signal: %w", err) + } + + // The waitid(2) supports P_PIDFD since Linux kernel v5.4. + // + // https://man7.org/linux/man-pages/man2/waitid.2.html + werr := IgnoringEINTR(func() error { + return unix.Waitid(unix.P_PIDFD, pidfd, nil, unix.WEXITED, nil) + }) + + // The waitid returns ECHILD since current process isn't the child of current process. + if !errors.Is(werr, unix.ECHILD) { + return fmt.Errorf("failed to invoke waitid with P_PIDFD: wanted error %v, but got %v", + unix.ECHILD, werr) + } + + // NOTE: The CLONE_PIDFD flag has been supported since Linux kernel v5.2. + // So assumption is that if waitid(2) supports P_PIDFD, current kernel + // should support CLONE_PIDFD as well. + return nil +} diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/socket_unix.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/socket_unix.go new file mode 100644 index 0000000000..5ecbeddc91 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/socket_unix.go @@ -0,0 +1,80 @@ +//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 sys + +import ( + "fmt" + "net" + "os" + "path/filepath" + + "golang.org/x/sys/unix" +) + +// CreateUnixSocket creates a unix socket and returns the listener +func CreateUnixSocket(path string) (net.Listener, error) { + // BSDs have a 104 limit + if len(path) > 104 { + return nil, fmt.Errorf("%q: unix socket path too long (> 104)", path) + } + if err := os.MkdirAll(filepath.Dir(path), 0660); err != nil { + return nil, err + } + if err := unix.Unlink(path); err != nil && !os.IsNotExist(err) { + return nil, err + } + return net.Listen("unix", path) +} + +// GetLocalListener returns a listener out of a unix socket. +func GetLocalListener(path string, uid, gid int) (net.Listener, error) { + // Ensure parent directory is created + if err := mkdirAs(filepath.Dir(path), uid, gid); err != nil { + return nil, err + } + + l, err := CreateUnixSocket(path) + if err != nil { + return l, err + } + + if err := os.Chmod(path, 0660); err != nil { + l.Close() + return nil, err + } + + if err := os.Chown(path, uid, gid); err != nil { + l.Close() + return nil, err + } + + return l, nil +} + +func mkdirAs(path string, uid, gid int) error { + if _, err := os.Stat(path); !os.IsNotExist(err) { + return err + } + + if err := os.MkdirAll(path, 0770); err != nil { + return err + } + + return os.Chown(path, uid, gid) +} diff --git a/vendor/github.com/containerd/platforms/platforms_other.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/socket_windows.go similarity index 63% rename from vendor/github.com/containerd/platforms/platforms_other.go rename to vendor/github.com/containerd/containerd/v2/pkg/sys/socket_windows.go index 03f4dcd998..1ae12bc511 100644 --- a/vendor/github.com/containerd/platforms/platforms_other.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/socket_windows.go @@ -1,5 +1,3 @@ -//go:build !windows - /* Copyright The containerd Authors. @@ -16,15 +14,17 @@ limitations under the License. */ -package platforms +package sys import ( - specs "github.com/opencontainers/image-spec/specs-go/v1" + "net" + + "github.com/Microsoft/go-winio" ) -// NewMatcher returns the default Matcher for containerd -func newDefaultMatcher(platform specs.Platform) Matcher { - return &matcher{ - Platform: Normalize(platform), - } +// GetLocalListener returns a Listernet out of a named pipe. +// `path` must be of the form of `\\.\pipe\` +// (see https://msdn.microsoft.com/en-us/library/windows/desktop/aa365150) +func GetLocalListener(path string, uid, gid int) (net.Listener, error) { + return winio.ListenPipe(path, nil) } diff --git a/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.go b/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.go new file mode 100644 index 0000000000..31f36323a5 --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/pkg/sys/unshare_linux.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 sys + +import ( + "errors" + "fmt" + "os" + "runtime" + "strconv" + "strings" + "syscall" + + "golang.org/x/sys/unix" +) + +// UnshareAfterEnterUserns allows to disassociate parts of its execution context +// within a user namespace. +func UnshareAfterEnterUserns(uidMap, gidMap string, unshareFlags uintptr, f func(pid int) error) (retErr error) { + if unshareFlags&syscall.CLONE_NEWUSER == syscall.CLONE_NEWUSER { + return fmt.Errorf("unshare flags should not include user namespace") + } + + uidMaps, err := parseIDMapping(uidMap) + if err != nil { + return err + } + + gidMaps, err := parseIDMapping(gidMap) + if err != nil { + return err + } + + var pidfd int + proc, err := os.StartProcess("/proc/self/exe", []string{"UnshareAfterEnterUserns"}, &os.ProcAttr{ + Sys: &syscall.SysProcAttr{ + // clone new user namespace first and then unshare + Cloneflags: unix.CLONE_NEWUSER, + Unshareflags: unshareFlags, + UidMappings: uidMaps, + GidMappings: gidMaps, + GidMappingsEnableSetgroups: true, + // NOTE: It's reexec but it's not heavy because subprocess + // be in PTRACE_TRACEME mode before performing execve. + Ptrace: true, + Pdeathsig: syscall.SIGKILL, + PidFD: &pidfd, + }, + }) + if err != nil { + return fmt.Errorf("failed to start noop process for unshare: %w", err) + } + + if pidfd == -1 || !SupportsPidFD() { + proc.Kill() + proc.Wait() + return fmt.Errorf("kernel doesn't support CLONE_PIDFD") + } + + // Since go1.23.{0,1} has double close issue, we should dup it before using it. + // + // References: + // - https://github.com/golang/go/issues/68984 + // - https://github.com/golang/go/milestone/371 + if goVer := runtime.Version(); goVer == "go1.23.0" || goVer == "go1.23.1" { + dupPidfd, dupErr := unix.FcntlInt(uintptr(pidfd), syscall.F_DUPFD_CLOEXEC, 0) + if dupErr != nil { + proc.Kill() + proc.Wait() + return fmt.Errorf("failed to dupfd: %w", err) + } + pidfd = dupPidfd + } + + defer func() { + derr := unix.PidfdSendSignal(pidfd, unix.SIGKILL, nil, 0) + if derr != nil { + if !errors.Is(derr, unix.ESRCH) { + retErr = derr + } + return + } + pidfdWaitid(pidfd) + }() + + if f != nil { + if err := f(proc.Pid); err != nil { + return err + } + } + + // Ensure the child process is still alive. If the err is ESRCH, we + // should return error because the pid could be reused. It's safe to + // return error and retry. + if err := unix.PidfdSendSignal(pidfd, 0, nil, 0); err != nil { + return fmt.Errorf("failed to ensure child process is alive: %w", err) + } + return nil +} + +// TODO: Support multiple mappings in future +func parseIDMapping(mapping string) ([]syscall.SysProcIDMap, error) { + parts := strings.Split(mapping, ":") + if len(parts) != 3 { + return nil, fmt.Errorf("user namespace mappings require the format `container-id:host-id:size`") + } + + cID, err := strconv.Atoi(parts[0]) + if err != nil { + return nil, fmt.Errorf("invalid container id for user namespace remapping, %w", err) + } + + hID, err := strconv.Atoi(parts[1]) + if err != nil { + return nil, fmt.Errorf("invalid host id for user namespace remapping, %w", err) + } + + size, err := strconv.Atoi(parts[2]) + if err != nil { + return nil, fmt.Errorf("invalid size for user namespace remapping, %w", err) + } + + if cID < 0 || hID < 0 || size < 0 { + return nil, fmt.Errorf("invalid mapping %s, all IDs and size must be positive integers", mapping) + } + + return []syscall.SysProcIDMap{ + { + ContainerID: cID, + HostID: hID, + Size: size, + }, + }, nil +} + +func pidfdWaitid(pidfd int) error { + return IgnoringEINTR(func() error { + return unix.Waitid(unix.P_PIDFD, pidfd, nil, unix.WEXITED, nil) + }) +} diff --git a/vendor/github.com/containerd/containerd/tracing/helpers.go b/vendor/github.com/containerd/containerd/v2/pkg/tracing/helpers.go similarity index 91% rename from vendor/github.com/containerd/containerd/tracing/helpers.go rename to vendor/github.com/containerd/containerd/v2/pkg/tracing/helpers.go index 981da6c795..ab1278ef1f 100644 --- a/vendor/github.com/containerd/containerd/tracing/helpers.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/tracing/helpers.go @@ -19,20 +19,11 @@ package tracing import ( "encoding/json" "fmt" - "strings" "go.opentelemetry.io/otel/attribute" ) -const ( - spanDelimiter = "." -) - -func makeSpanName(names ...string) string { - return strings.Join(names, spanDelimiter) -} - -func any(k string, v interface{}) attribute.KeyValue { +func keyValue(k string, v any) attribute.KeyValue { if v == nil { return attribute.String(k, "") } diff --git a/vendor/github.com/containerd/containerd/tracing/log.go b/vendor/github.com/containerd/containerd/v2/pkg/tracing/log.go similarity index 64% rename from vendor/github.com/containerd/containerd/tracing/log.go rename to vendor/github.com/containerd/containerd/v2/pkg/tracing/log.go index 98fa16f931..3af24a294a 100644 --- a/vendor/github.com/containerd/containerd/tracing/log.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/tracing/log.go @@ -17,33 +17,49 @@ package tracing import ( - "github.com/sirupsen/logrus" + "github.com/containerd/log" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" ) +// allLevels is the equivalent to [logrus.AllLevels]. +// +// [logrus.AllLevels]: https://github.com/sirupsen/logrus/blob/v1.9.3/logrus.go#L80-L89 +var allLevels = []log.Level{ + log.PanicLevel, + log.FatalLevel, + log.ErrorLevel, + log.WarnLevel, + log.InfoLevel, + log.DebugLevel, + log.TraceLevel, +} + // NewLogrusHook creates a new logrus hook func NewLogrusHook() *LogrusHook { return &LogrusHook{} } -// LogrusHook is a logrus hook which adds logrus events to active spans. -// If the span is not recording or the span context is invalid, the hook is a no-op. +// LogrusHook is a [logrus.Hook] which adds logrus events to active spans. +// If the span is not recording or the span context is invalid, the hook +// is a no-op. +// +// [logrus.Hook]: https://github.com/sirupsen/logrus/blob/v1.9.3/hooks.go#L3-L11 type LogrusHook struct{} // Levels returns the logrus levels that this hook is interested in. -func (h *LogrusHook) Levels() []logrus.Level { - return logrus.AllLevels +func (h *LogrusHook) Levels() []log.Level { + return allLevels } // Fire is called when a log event occurs. -func (h *LogrusHook) Fire(entry *logrus.Entry) error { +func (h *LogrusHook) Fire(entry *log.Entry) error { span := trace.SpanFromContext(entry.Context) if span == nil { return nil } - if !span.SpanContext().IsValid() || !span.IsRecording() { + if !span.IsRecording() || !span.SpanContext().IsValid() { return nil } @@ -57,10 +73,10 @@ func (h *LogrusHook) Fire(entry *logrus.Entry) error { return nil } -func logrusDataToAttrs(data logrus.Fields) []attribute.KeyValue { +func logrusDataToAttrs(data map[string]any) []attribute.KeyValue { attrs := make([]attribute.KeyValue, 0, len(data)) for k, v := range data { - attrs = append(attrs, any(k, v)) + attrs = append(attrs, keyValue(k, v)) } return attrs } diff --git a/vendor/github.com/containerd/containerd/tracing/tracing.go b/vendor/github.com/containerd/containerd/v2/pkg/tracing/tracing.go similarity index 81% rename from vendor/github.com/containerd/containerd/tracing/tracing.go rename to vendor/github.com/containerd/containerd/v2/pkg/tracing/tracing.go index 80d2b95c0e..48d760feb8 100644 --- a/vendor/github.com/containerd/containerd/tracing/tracing.go +++ b/vendor/github.com/containerd/containerd/v2/pkg/tracing/tracing.go @@ -19,6 +19,7 @@ package tracing import ( "context" "net/http" + "strings" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" "go.opentelemetry.io/otel" @@ -35,16 +36,11 @@ type StartConfig struct { type SpanOpt func(config *StartConfig) -// WithHTTPRequest marks span as a HTTP request operation from client to server. -// It'll append attributes from the HTTP request object and mark it with `SpanKindClient` type. -// -// Deprecated: use upstream functionality from otelhttp directly instead. This function is kept for API compatibility -// but no longer works as expected due to required functionality no longer exported in OpenTelemetry libraries. -func WithHTTPRequest(_ *http.Request) SpanOpt { +// WithAttribute appends attributes to a new created span. +func WithAttribute(k string, v interface{}) SpanOpt { return func(config *StartConfig) { config.spanOpts = append(config.spanOpts, - trace.WithSpanKind(trace.SpanKindClient), // A client making a request to a server - ) + trace.WithAttributes(Attribute(k, v))) } } @@ -92,8 +88,13 @@ func (s *Span) End() { } // AddEvent adds an event with provided name and options. -func (s *Span) AddEvent(name string, options ...trace.EventOption) { - s.otelSpan.AddEvent(name, options...) +func (s *Span) AddEvent(name string, attributes ...attribute.KeyValue) { + s.otelSpan.AddEvent(name, trace.WithAttributes(attributes...)) +} + +// RecordError will record err as an exception span event for this span +func (s *Span) RecordError(err error, options ...trace.EventOption) { + s.otelSpan.RecordError(err, options...) } // SetStatus sets the status of the current span. @@ -112,14 +113,16 @@ func (s *Span) SetAttributes(kv ...attribute.KeyValue) { s.otelSpan.SetAttributes(kv...) } +const spanDelimiter = "." + // Name sets the span name by joining a list of strings in dot separated format. func Name(names ...string) string { - return makeSpanName(names...) + return strings.Join(names, spanDelimiter) } // Attribute takes a key value pair and returns attribute.KeyValue type. -func Attribute(k string, v interface{}) attribute.KeyValue { - return any(k, v) +func Attribute(k string, v any) attribute.KeyValue { + return keyValue(k, v) } // HTTPStatusCodeAttributes generates attributes of the HTTP namespace as specified by the OpenTelemetry diff --git a/vendor/github.com/containerd/containerd/content/local/content_local_fuzzer.go b/vendor/github.com/containerd/containerd/v2/plugins/content/local/content_local_fuzzer.go similarity index 96% rename from vendor/github.com/containerd/containerd/content/local/content_local_fuzzer.go rename to vendor/github.com/containerd/containerd/v2/plugins/content/local/content_local_fuzzer.go index a523f28d91..39ec84b375 100644 --- a/vendor/github.com/containerd/containerd/content/local/content_local_fuzzer.go +++ b/vendor/github.com/containerd/containerd/v2/plugins/content/local/content_local_fuzzer.go @@ -28,7 +28,7 @@ import ( "github.com/opencontainers/go-digest" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" ) func FuzzContentStoreWriter(data []byte) int { diff --git a/vendor/github.com/containerd/containerd/content/local/locks.go b/vendor/github.com/containerd/containerd/v2/plugins/content/local/locks.go similarity index 73% rename from vendor/github.com/containerd/containerd/content/local/locks.go rename to vendor/github.com/containerd/containerd/v2/plugins/content/local/locks.go index 1e59f39b30..80795add32 100644 --- a/vendor/github.com/containerd/containerd/content/local/locks.go +++ b/vendor/github.com/containerd/containerd/v2/plugins/content/local/locks.go @@ -18,10 +18,9 @@ package local import ( "fmt" - "sync" "time" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/errdefs" ) // Handles locking references @@ -30,17 +29,11 @@ type lock struct { since time.Time } -var ( - // locks lets us lock in process - locks = make(map[string]*lock) - locksMu sync.Mutex -) +func (s *store) tryLock(ref string) error { + s.locksMu.Lock() + defer s.locksMu.Unlock() -func tryLock(ref string) error { - locksMu.Lock() - defer locksMu.Unlock() - - if v, ok := locks[ref]; ok { + if v, ok := s.locks[ref]; ok { // Returning the duration may help developers distinguish dead locks (long duration) from // lock contentions (short duration). now := time.Now() @@ -50,13 +43,13 @@ func tryLock(ref string) error { ) } - locks[ref] = &lock{time.Now()} + s.locks[ref] = &lock{time.Now()} return nil } -func unlock(ref string) { - locksMu.Lock() - defer locksMu.Unlock() +func (s *store) unlock(ref string) { + s.locksMu.Lock() + defer s.locksMu.Unlock() - delete(locks, ref) + delete(s.locks, ref) } diff --git a/vendor/github.com/containerd/containerd/content/local/readerat.go b/vendor/github.com/containerd/containerd/v2/plugins/content/local/readerat.go similarity index 94% rename from vendor/github.com/containerd/containerd/content/local/readerat.go rename to vendor/github.com/containerd/containerd/v2/plugins/content/local/readerat.go index 899e85c0ba..59198fd6e9 100644 --- a/vendor/github.com/containerd/containerd/content/local/readerat.go +++ b/vendor/github.com/containerd/containerd/v2/plugins/content/local/readerat.go @@ -21,8 +21,8 @@ import ( "io" "os" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/errdefs" ) // readerat implements io.ReaderAt in a completely stateless manner by opening diff --git a/vendor/github.com/containerd/containerd/content/local/store.go b/vendor/github.com/containerd/containerd/v2/plugins/content/local/store.go similarity index 95% rename from vendor/github.com/containerd/containerd/content/local/store.go rename to vendor/github.com/containerd/containerd/v2/plugins/content/local/store.go index efe886014c..794c82c25e 100644 --- a/vendor/github.com/containerd/containerd/content/local/store.go +++ b/vendor/github.com/containerd/containerd/v2/plugins/content/local/store.go @@ -27,13 +27,12 @@ import ( "sync" "time" + "github.com/containerd/errdefs" "github.com/containerd/log" - "github.com/sirupsen/logrus" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/pkg/randutil" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/internal/fsverity" + "github.com/containerd/containerd/v2/pkg/filters" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" @@ -65,9 +64,12 @@ type LabelStore interface { // Store can generally support multi-reader, single-writer ingest of data, // including resumable ingest. type store struct { - root string - ls LabelStore + root string + ls LabelStore + integritySupported bool + locksMu sync.Mutex + locks map[string]*lock ensureIngestRootOnce func() error } @@ -82,11 +84,14 @@ func NewStore(root string) (content.Store, error) { // require labels and should use `NewStore`. `NewLabeledStore` is primarily // useful for tests or standalone implementations. func NewLabeledStore(root string, ls LabelStore) (content.Store, error) { - s := &store{ - root: root, - ls: ls, - } + supported, _ := fsverity.IsSupported(root) + s := &store{ + root: root, + ls: ls, + integritySupported: supported, + locks: map[string]*lock{}, + } s.ensureIngestRootOnce = sync.OnceValue(s.ensureIngestRoot) return s, nil } @@ -300,10 +305,9 @@ func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Statu } return nil, err } - defer fp.Close() - fis, err := fp.Readdir(-1) + fis, err := fp.Readdirnames(-1) if err != nil { return nil, err } @@ -315,7 +319,7 @@ func (s *store) ListStatuses(ctx context.Context, fs ...string) ([]content.Statu var active []content.Status for _, fi := range fis { - p := filepath.Join(s.root, "ingest", fi.Name()) + p := filepath.Join(s.root, "ingest", fi) stat, err := s.status(p) if err != nil { if !os.IsNotExist(err) { @@ -353,16 +357,15 @@ func (s *store) WalkStatusRefs(ctx context.Context, fn func(string) error) error } return err } - defer fp.Close() - fis, err := fp.Readdir(-1) + fis, err := fp.Readdirnames(-1) if err != nil { return err } for _, fi := range fis { - rf := filepath.Join(s.root, "ingest", fi.Name(), "ref") + rf := filepath.Join(s.root, "ingest", fi, "ref") ref, err := readFileString(rf) if err != nil { @@ -469,28 +472,14 @@ func (s *store) Writer(ctx context.Context, opts ...content.WriterOpt) (content. if wOpts.Ref == "" { return nil, fmt.Errorf("ref must not be empty: %w", errdefs.ErrInvalidArgument) } - var lockErr error - for count := uint64(0); count < 10; count++ { - if err := tryLock(wOpts.Ref); err != nil { - if !errdefs.IsUnavailable(err) { - return nil, err - } - lockErr = err - } else { - lockErr = nil - break - } - time.Sleep(time.Millisecond * time.Duration(randutil.Intn(1<= 100 { if err := sendBlock(buffer); err != nil { @@ -119,7 +117,7 @@ func (s *service) List(req *api.ListContentRequest, session api.Content_ListServ return nil }, req.Filters...); err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } if len(buffer) > 0 { @@ -140,10 +138,10 @@ func (s *service) Delete(ctx context.Context, req *api.DeleteContentRequest) (*p } if err := s.store.Delete(ctx, dg); err != nil { - return nil, errdefs.ToGRPC(err) + return nil, errgrpc.ToGRPC(err) } - return &ptypes.Empty{}, nil + return empty, nil } func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServer) error { @@ -154,12 +152,12 @@ func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServ oi, err := s.store.Info(session.Context(), dg) if err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } ra, err := s.store.ReaderAt(session.Context(), ocispec.Descriptor{Digest: dg}) if err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } defer ra.Close() @@ -190,7 +188,7 @@ func (s *service) Read(req *api.ReadContentRequest, session api.Content_ReadServ _, err = io.CopyBuffer( &readResponseWriter{session: session}, io.NewSectionReader(ra, offset, size), *p) - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } // readResponseWriter is a writer that places the output into ReadContentRequest messages. @@ -217,7 +215,7 @@ func (rw *readResponseWriter) Write(p []byte) (n int, err error) { func (s *service) Status(ctx context.Context, req *api.StatusRequest) (*api.StatusResponse, error) { status, err := s.store.Status(ctx, req.Ref) if err != nil { - return nil, errdefs.ToGRPCf(err, "could not get status for ref %q", req.Ref) + return nil, errgrpc.ToGRPCf(err, "could not get status for ref %q", req.Ref) } var resp api.StatusResponse @@ -236,7 +234,7 @@ func (s *service) Status(ctx context.Context, req *api.StatusRequest) (*api.Stat func (s *service) ListStatuses(ctx context.Context, req *api.ListStatusesRequest) (*api.ListStatusesResponse, error) { statuses, err := s.store.ListStatuses(ctx, req.Filters...) if err != nil { - return nil, errdefs.ToGRPC(err) + return nil, errgrpc.ToGRPC(err) } var resp api.ListStatusesResponse @@ -316,7 +314,7 @@ func (s *service) Write(session api.Content_WriteServer) (err error) { content.WithRef(ref), content.WithDescriptor(ocispec.Descriptor{Size: total, Digest: expected})) if err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } defer wr.Close() @@ -324,7 +322,7 @@ func (s *service) Write(session api.Content_WriteServer) (err error) { msg.Action = req.Action ws, err := wr.Status() if err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } msg.Offset = ws.Offset // always set the offset. @@ -401,7 +399,7 @@ func (s *service) Write(session api.Content_WriteServer) (err error) { // maintain the offset as append only, we just issue the write. n, err := wr.Write(req.Data) if err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } if n != len(req.Data) { @@ -419,7 +417,7 @@ func (s *service) Write(session api.Content_WriteServer) (err error) { opts = append(opts, content.WithLabels(req.Labels)) } if err := wr.Commit(ctx, total, expected, opts...); err != nil { - return errdefs.ToGRPC(err) + return errgrpc.ToGRPC(err) } } @@ -447,10 +445,10 @@ func (s *service) Write(session api.Content_WriteServer) (err error) { func (s *service) Abort(ctx context.Context, req *api.AbortRequest) (*ptypes.Empty, error) { if err := s.store.Abort(ctx, req.Ref); err != nil { - return nil, errdefs.ToGRPC(err) + return nil, errgrpc.ToGRPC(err) } - return &ptypes.Empty{}, nil + return empty, nil } func infoToGRPC(info content.Info) *api.Info { diff --git a/vendor/github.com/containerd/containerd/services/services.go b/vendor/github.com/containerd/containerd/v2/plugins/services/services.go similarity index 89% rename from vendor/github.com/containerd/containerd/services/services.go rename to vendor/github.com/containerd/containerd/v2/plugins/services/services.go index d7255169f1..7c794de2ab 100644 --- a/vendor/github.com/containerd/containerd/services/services.go +++ b/vendor/github.com/containerd/containerd/v2/plugins/services/services.go @@ -21,6 +21,8 @@ const ( ContentService = "content-service" // SnapshotsService is id of snapshots service. SnapshotsService = "snapshots-service" + // SandboxControllersService is id of snapshots service. + SandboxControllersService = "sandboxes-service" // ImagesService is id of images service. ImagesService = "images-service" // ContainersService is id of containers service. @@ -33,6 +35,6 @@ const ( DiffService = "diff-service" // IntrospectionService is the id of introspection service IntrospectionService = "introspection-service" - // Streaming service is the id of the streaming service + // StreamingService is the id of the streaming service StreamingService = "streaming-service" ) diff --git a/vendor/github.com/containerd/containerd/snapshots/overlay/overlayutils/check.go b/vendor/github.com/containerd/containerd/v2/plugins/snapshots/overlay/overlayutils/check.go similarity index 63% rename from vendor/github.com/containerd/containerd/snapshots/overlay/overlayutils/check.go rename to vendor/github.com/containerd/containerd/v2/plugins/snapshots/overlay/overlayutils/check.go index 23a39e016d..fd943777d2 100644 --- a/vendor/github.com/containerd/containerd/snapshots/overlay/overlayutils/check.go +++ b/vendor/github.com/containerd/containerd/v2/plugins/snapshots/overlay/overlayutils/check.go @@ -25,9 +25,10 @@ import ( "syscall" "github.com/moby/sys/userns" + "golang.org/x/sys/unix" - kernel "github.com/containerd/containerd/contrib/seccomp/kernelversion" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" + kernel "github.com/containerd/containerd/v2/pkg/kernelversion" "github.com/containerd/continuity/fs" "github.com/containerd/log" ) @@ -199,3 +200,98 @@ func NeedsUserXAttr(d string) (bool, error) { } return true, nil } + +// SupportsIDMappedMounts tells if this kernel supports idmapped mounts for overlayfs +// or not. +// +// This function returns error whether the kernel supports idmapped mounts +// for overlayfs or not, i.e. if e.g. -ENOSYS may be returned as well as -EPERM. +// So, caller should check for (true, err == nil), otherwise treat it as there's +// no support from the kernel side. +func SupportsIDMappedMounts() (bool, error) { + // Fast path + fiveDotNineteen := kernel.KernelVersion{Kernel: 5, Major: 19} + if ok, err := kernel.GreaterEqualThan(fiveDotNineteen); err == nil && ok { + return true, nil + } + + // Do slow path, because idmapped mounts may be backported to older kernels. + uidMap := syscall.SysProcIDMap{ + ContainerID: 0, + HostID: 666, + Size: 1, + } + gidMap := syscall.SysProcIDMap{ + ContainerID: 0, + HostID: 666, + Size: 1, + } + td, err := os.MkdirTemp("", "ovl-idmapped-check") + if err != nil { + return false, fmt.Errorf("failed to create check directory: %w", err) + } + defer func() { + if err := os.RemoveAll(td); err != nil { + log.L.WithError(err).Warnf("failed to remove check directory %s", td) + } + }() + + for _, dir := range []string{"lower", "upper", "work", "merged"} { + if err = os.Mkdir(filepath.Join(td, dir), 0755); err != nil { + return false, fmt.Errorf("failed to create %s directory: %w", dir, err) + } + } + defer func() { + if err = os.RemoveAll(td); err != nil { + log.L.WithError(err).Warnf("failed remove overlay check directory %s", td) + } + }() + + if err = os.Lchown(filepath.Join(td, "upper"), uidMap.HostID, gidMap.HostID); err != nil { + return false, fmt.Errorf("failed to chown upper directory %s: %w", filepath.Join(td, "upper"), err) + } + + lowerDir := filepath.Join(td, "lower") + uidmap := fmt.Sprintf("%d:%d:%d", uidMap.ContainerID, uidMap.HostID, uidMap.Size) + gidmap := fmt.Sprintf("%d:%d:%d", gidMap.ContainerID, gidMap.HostID, gidMap.Size) + + usernsFd, err := mount.GetUsernsFD(uidmap, gidmap) + if err != nil { + return false, err + } + defer usernsFd.Close() + + if err = mount.IDMapMount(lowerDir, lowerDir, int(usernsFd.Fd())); err != nil { + return false, fmt.Errorf("failed to remap lowerdir %s: %w", lowerDir, err) + } + defer func() { + if err = unix.Unmount(lowerDir, 0); err != nil { + log.L.WithError(err).Warnf("failed to unmount lowerdir %s", lowerDir) + } + }() + + opts := fmt.Sprintf("index=off,lowerdir=%s,upperdir=%s,workdir=%s", lowerDir, filepath.Join(td, "upper"), filepath.Join(td, "work")) + if err = unix.Mount("", filepath.Join(td, "merged"), "overlay", uintptr(unix.MS_RDONLY), opts); err != nil { + return false, fmt.Errorf("failed to mount idmapped overlay to %s: %w", filepath.Join(td, "merged"), err) + } + defer func() { + if err = unix.Unmount(filepath.Join(td, "merged"), 0); err != nil { + log.L.WithError(err).Warnf("failed to unmount overlay check directory %s", filepath.Join(td, "merged")) + } + }() + + // NOTE: we can't just return true if mount didn't fail since overlay supports + // idmappings for {lower,upper}dir. That means we need to check merged directory + // to make sure it completely supports idmapped mounts. + st, err := os.Stat(filepath.Join(td, "merged")) + if err != nil { + return false, fmt.Errorf("failed to stat %s: %w", filepath.Join(td, "merged"), err) + } + if stat, ok := st.Sys().(*syscall.Stat_t); !ok { + return false, fmt.Errorf("incompatible types after stat call: *syscall.Stat_t expected") + } else if int(stat.Uid) != uidMap.HostID || int(stat.Gid) != gidMap.HostID { + return false, fmt.Errorf("bad mapping: expected {uid: %d, gid: %d}; real {uid: %d, gid: %d}", uidMap.HostID, gidMap.HostID, int(stat.Uid), int(stat.Gid)) + } + + return true, nil +} diff --git a/vendor/github.com/containerd/containerd/v2/plugins/types.go b/vendor/github.com/containerd/containerd/v2/plugins/types.go new file mode 100644 index 0000000000..c63320678a --- /dev/null +++ b/vendor/github.com/containerd/containerd/v2/plugins/types.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. +*/ + +// plugins package stores all the plugin types used by containerd internally. +// +// External plugins should copy from these types and avoid importing this +// package. +package plugins + +import "github.com/containerd/plugin" + +const ( + // InternalPlugin implements an internal plugin to containerd + InternalPlugin plugin.Type = "io.containerd.internal.v1" + // RuntimePlugin implements a runtime + RuntimePlugin plugin.Type = "io.containerd.runtime.v1" + // RuntimePluginV2 implements a runtime v2 + RuntimePluginV2 plugin.Type = "io.containerd.runtime.v2" + // ServicePlugin implements a internal service + ServicePlugin plugin.Type = "io.containerd.service.v1" + // GRPCPlugin implements a grpc service + GRPCPlugin plugin.Type = "io.containerd.grpc.v1" + // TTRPCPlugin implements a ttrpc shim service + TTRPCPlugin plugin.Type = "io.containerd.ttrpc.v1" + // SnapshotPlugin implements a snapshotter + SnapshotPlugin plugin.Type = "io.containerd.snapshotter.v1" + // TaskMonitorPlugin implements a task monitor + TaskMonitorPlugin plugin.Type = "io.containerd.monitor.task.v1" + // TaskMonitorPlugin implements a container monitor + ContainerMonitorPlugin plugin.Type = "io.containerd.monitor.container.v1" + // DiffPlugin implements a differ + DiffPlugin plugin.Type = "io.containerd.differ.v1" + // MetadataPlugin implements a metadata store + MetadataPlugin plugin.Type = "io.containerd.metadata.v1" + // ContentPlugin implements a content store + ContentPlugin plugin.Type = "io.containerd.content.v1" + // GCPlugin implements garbage collection policy + GCPlugin plugin.Type = "io.containerd.gc.v1" + // EventPlugin implements event handling + EventPlugin plugin.Type = "io.containerd.event.v1" + // LeasePlugin implements lease manager + LeasePlugin plugin.Type = "io.containerd.lease.v1" + // StreamingPlugin implements a stream manager + StreamingPlugin plugin.Type = "io.containerd.streaming.v1" + // TracingProcessorPlugin implements a open telemetry span processor + TracingProcessorPlugin plugin.Type = "io.containerd.tracing.processor.v1" + // NRIApiPlugin implements the NRI adaptation interface for containerd. + NRIApiPlugin plugin.Type = "io.containerd.nri.v1" + // TransferPlugin implements a transfer service + TransferPlugin plugin.Type = "io.containerd.transfer.v1" + // SandboxStorePlugin implements a sandbox store + SandboxStorePlugin plugin.Type = "io.containerd.sandbox.store.v1" + // PodSandboxPlugin is a special sandbox controller which use pause container as a sandbox. + PodSandboxPlugin plugin.Type = "io.containerd.podsandbox.controller.v1" + // SandboxControllerPlugin implements a sandbox controller + SandboxControllerPlugin plugin.Type = "io.containerd.sandbox.controller.v1" + // ImageVerifierPlugin implements an image verifier service + ImageVerifierPlugin plugin.Type = "io.containerd.image-verifier.v1" + // WarningPlugin implements a warning service + WarningPlugin plugin.Type = "io.containerd.warning.v1" + // CRIServicePlugin implements a cri service + CRIServicePlugin plugin.Type = "io.containerd.cri.v1" + // ShimPlugin implements a shim service + ShimPlugin plugin.Type = "io.containerd.shim.v1" + // HTTPHandler implements an http handler + HTTPHandler plugin.Type = "io.containerd.http.v1" +) + +const ( + // RuntimeRuncV2 is the runc runtime that supports multiple containers per shim + RuntimeRuncV2 = "io.containerd.runc.v2" + + // RuntimeRunhcsV1 is the runtime type for runhcs. + RuntimeRunhcsV1 = "io.containerd.runhcs.v1" + + DeprecationsPlugin = "deprecations" +) + +const ( + // PropertyRootDir sets the root directory property for a plugin + PropertyRootDir = "io.containerd.plugin.root" + // PropertyStateDir sets the state directory property for a plugin + PropertyStateDir = "io.containerd.plugin.state" + // PropertyGRPCAddress is the grpc address used for client connections to containerd + PropertyGRPCAddress = "io.containerd.plugin.grpc.address" + // PropertyTTRPCAddress is the ttrpc address used for client connections to containerd + PropertyTTRPCAddress = "io.containerd.plugin.ttrpc.address" +) + +const ( + SnapshotterRootDir = "root" +) diff --git a/vendor/github.com/containerd/containerd/version/version.go b/vendor/github.com/containerd/containerd/v2/version/version.go similarity index 70% rename from vendor/github.com/containerd/containerd/version/version.go rename to vendor/github.com/containerd/containerd/v2/version/version.go index 2439eabf9e..28f46ed09c 100644 --- a/vendor/github.com/containerd/containerd/version/version.go +++ b/vendor/github.com/containerd/containerd/v2/version/version.go @@ -20,10 +20,10 @@ import "runtime" var ( // Package is filled at linking time - Package = "github.com/containerd/containerd" + Package = "github.com/containerd/containerd/v2" // Version holds the complete version number. Filled in at linking time. - Version = "1.7.25+unknown" + Version = "2.0.2+unknown" // Revision is filled with the VCS (e.g. git) revision being used to build // the program at linking time. @@ -32,3 +32,9 @@ var ( // GoVersion is Go tree's version. GoVersion = runtime.Version() ) + +// ConfigVersion is the current highest supported configuration version. +// This version is used by the main configuration as well as all plugins. +// Any configuration less than this version which has structural changes +// should migrate the configuration structures used by this version. +const ConfigVersion = 3 diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_unix.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_unix.go index c892c68511..4d0dda0d39 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_unix.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_unix.go @@ -22,13 +22,13 @@ import ( "sync" "syscall" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/local" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/images/converter" - "github.com/containerd/containerd/labels" + "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/pkg/archive" + "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/plugins/content/local" "github.com/containerd/errdefs" "github.com/containerd/fifo" "github.com/klauspost/compress/zstd" diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_windows.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_windows.go index f3bf6bea0c..c0a570d3c0 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_windows.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/convert_windows.go @@ -13,8 +13,8 @@ import ( "context" "io" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images/converter" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images/converter" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/cs_proxy_unix.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/cs_proxy_unix.go index 43c8e02287..7a3af70927 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/cs_proxy_unix.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/cs_proxy_unix.go @@ -20,7 +20,7 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/tool/builder.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/tool/builder.go index 78f860029a..7a789b1a3a 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/tool/builder.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/tool/builder.go @@ -305,7 +305,33 @@ func Unpack(option UnpackOption) error { } if option.BackendConfigPath != "" { - args = append(args, "--backend-config", option.BackendConfigPath) + configBytes, err := os.ReadFile(option.BackendConfigPath) + if err != nil { + return errors.Wrapf(err, "fail to read backend config file %s", option.BackendConfigPath) + } + + var config map[string]interface{} + if err := json.Unmarshal(configBytes, &config); err != nil { + return errors.Wrapf(err, "fail to unmarshal backend config file %s", option.BackendConfigPath) + } + + backendConfigType, ok := config["backend"].(map[string]interface{})["type"] + if !ok { + return errors.New("backend config file should contain a valid backend type") + } + + backendConfig, ok := config["backend"].(map[string]interface{})[backendConfigType.(string)] + if !ok { + return errors.New("failed to get backend config with type " + backendConfigType.(string)) + } + + backendConfigBytes, err := json.Marshal(backendConfig) + if err != nil { + return errors.Wrapf(err, "fail to marshal backend config %v", backendConfig) + } + + args = append(args, "--backend-type", backendConfigType.(string)) + args = append(args, "--backend-config", string(backendConfigBytes)) } else if option.BlobPath != "" { args = append(args, "--blob", option.BlobPath) } diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/types.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/types.go index 6bd54a6afc..9827d0a377 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/types.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/types.go @@ -13,7 +13,7 @@ import ( "strings" "time" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/containerd/nydus-snapshotter/pkg/converter/tool" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/utils.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/utils.go index 7c09f76d0b..74dabec318 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/utils.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/converter/utils.go @@ -16,7 +16,7 @@ import ( "io" "path/filepath" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/opencontainers/go-digest" ocispec "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/containerd/nydus-snapshotter/pkg/label/label.go b/vendor/github.com/containerd/nydus-snapshotter/pkg/label/label.go index f5392771d4..f6368f5360 100644 --- a/vendor/github.com/containerd/nydus-snapshotter/pkg/label/label.go +++ b/vendor/github.com/containerd/nydus-snapshotter/pkg/label/label.go @@ -7,7 +7,7 @@ package label import ( - snpkg "github.com/containerd/containerd/pkg/snapshotters" + snpkg "github.com/containerd/containerd/v2/pkg/snapshotters" ) // For package compatibility, we still keep the old exported name here. diff --git a/vendor/github.com/containerd/platforms/.golangci.yml b/vendor/github.com/containerd/platforms/.golangci.yml index a695775df4..d574fe11d7 100644 --- a/vendor/github.com/containerd/platforms/.golangci.yml +++ b/vendor/github.com/containerd/platforms/.golangci.yml @@ -1,6 +1,6 @@ linters: enable: - - exportloopref # Checks for pointers to enclosing loop variables + - copyloopvar - gofmt - goimports - gosec @@ -12,14 +12,16 @@ linters: - tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17 - unconvert - unused - - vet + - govet - dupword # Checks for duplicate words in the source code disable: - errcheck run: timeout: 5m - skip-dirs: + +issues: + exclude-dirs: - api - cluster - design diff --git a/vendor/github.com/containerd/platforms/compare.go b/vendor/github.com/containerd/platforms/compare.go index 3913ef6637..24403f3b3d 100644 --- a/vendor/github.com/containerd/platforms/compare.go +++ b/vendor/github.com/containerd/platforms/compare.go @@ -31,6 +31,34 @@ type MatchComparer interface { Less(specs.Platform, specs.Platform) bool } +type platformVersions struct { + major []int + minor []int +} + +var arm64variantToVersion = map[string]platformVersions{ + "v8": {[]int{8}, []int{0}}, + "v8.0": {[]int{8}, []int{0}}, + "v8.1": {[]int{8}, []int{1}}, + "v8.2": {[]int{8}, []int{2}}, + "v8.3": {[]int{8}, []int{3}}, + "v8.4": {[]int{8}, []int{4}}, + "v8.5": {[]int{8}, []int{5}}, + "v8.6": {[]int{8}, []int{6}}, + "v8.7": {[]int{8}, []int{7}}, + "v8.8": {[]int{8}, []int{8}}, + "v8.9": {[]int{8}, []int{9}}, + "v9": {[]int{9, 8}, []int{0, 5}}, + "v9.0": {[]int{9, 8}, []int{0, 5}}, + "v9.1": {[]int{9, 8}, []int{1, 6}}, + "v9.2": {[]int{9, 8}, []int{2, 7}}, + "v9.3": {[]int{9, 8}, []int{3, 8}}, + "v9.4": {[]int{9, 8}, []int{4, 9}}, + "v9.5": {[]int{9, 8}, []int{5, 9}}, + "v9.6": {[]int{9, 8}, []int{6, 9}}, + "v9.7": {[]int{9, 8}, []int{7, 9}}, +} + // platformVector returns an (ordered) vector of appropriate specs.Platform // objects to try matching for the given platform object (see platforms.Only). func platformVector(platform specs.Platform) []specs.Platform { @@ -72,6 +100,33 @@ func platformVector(platform specs.Platform) []specs.Platform { if variant == "" { variant = "v8" } + + vector = []specs.Platform{} // Reset vector, the first variant will be added in loop. + arm64Versions, ok := arm64variantToVersion[variant] + if !ok { + break + } + for i, major := range arm64Versions.major { + for minor := arm64Versions.minor[i]; minor >= 0; minor-- { + arm64Variant := "v" + strconv.Itoa(major) + "." + strconv.Itoa(minor) + if minor == 0 { + arm64Variant = "v" + strconv.Itoa(major) + } + vector = append(vector, specs.Platform{ + Architecture: "arm64", + OS: platform.OS, + OSVersion: platform.OSVersion, + OSFeatures: platform.OSFeatures, + Variant: arm64Variant, + }) + } + } + + // All arm64/v8.x and arm64/v9.x are compatible with arm/v8 (32-bits) and below. + // There's no arm64 v9 variant, so it's normalized to v8. + if strings.HasPrefix(variant, "v8") || strings.HasPrefix(variant, "v9") { + variant = "v8" + } vector = append(vector, platformVector(specs.Platform{ Architecture: "arm", OS: platform.OS, @@ -87,6 +142,8 @@ func platformVector(platform specs.Platform) []specs.Platform { // Only returns a match comparer for a single platform // using default resolution logic for the platform. // +// For arm64/v9.x, will also match arm64/v9.{0..x-1} and arm64/v8.{0..x+5} +// For arm64/v8.x, will also match arm64/v8.{0..x-1} // For arm/v8, will also match arm/v7, arm/v6 and arm/v5 // For arm/v7, will also match arm/v6 and arm/v5 // For arm/v6, will also match arm/v5 diff --git a/vendor/github.com/containerd/platforms/database.go b/vendor/github.com/containerd/platforms/database.go index 2e26fd3b4f..7a6f0d98cd 100644 --- a/vendor/github.com/containerd/platforms/database.go +++ b/vendor/github.com/containerd/platforms/database.go @@ -87,8 +87,10 @@ func normalizeArch(arch, variant string) (string, string) { case "aarch64", "arm64": arch = "arm64" switch variant { - case "8", "v8": + case "8", "v8", "v8.0": variant = "" + case "9", "9.0", "v9.0": + variant = "v9" } case "armhf": arch = "arm" diff --git a/vendor/github.com/containerd/platforms/defaults_windows.go b/vendor/github.com/containerd/platforms/defaults_windows.go index 427ed72eb6..0165adea7e 100644 --- a/vendor/github.com/containerd/platforms/defaults_windows.go +++ b/vendor/github.com/containerd/platforms/defaults_windows.go @@ -19,8 +19,6 @@ package platforms import ( "fmt" "runtime" - "strconv" - "strings" specs "github.com/opencontainers/image-spec/specs-go/v1" "golang.org/x/sys/windows" @@ -38,80 +36,6 @@ func DefaultSpec() specs.Platform { } } -type windowsmatcher struct { - specs.Platform - osVersionPrefix string - defaultMatcher Matcher -} - -// Match matches platform with the same windows major, minor -// and build version. -func (m windowsmatcher) Match(p specs.Platform) bool { - match := m.defaultMatcher.Match(p) - - if match && m.OS == "windows" { - // HPC containers do not have OS version filled - if m.OSVersion == "" || p.OSVersion == "" { - return true - } - - hostOsVersion := getOSVersion(m.osVersionPrefix) - ctrOsVersion := getOSVersion(p.OSVersion) - return checkHostAndContainerCompat(hostOsVersion, ctrOsVersion) - } - - return match -} - -func getOSVersion(osVersionPrefix string) osVersion { - parts := strings.Split(osVersionPrefix, ".") - if len(parts) < 3 { - return osVersion{} - } - - majorVersion, _ := strconv.Atoi(parts[0]) - minorVersion, _ := strconv.Atoi(parts[1]) - buildNumber, _ := strconv.Atoi(parts[2]) - - return osVersion{ - MajorVersion: uint8(majorVersion), - MinorVersion: uint8(minorVersion), - Build: uint16(buildNumber), - } -} - -// Less sorts matched platforms in front of other platforms. -// For matched platforms, it puts platforms with larger revision -// number in front. -func (m windowsmatcher) Less(p1, p2 specs.Platform) bool { - m1, m2 := m.Match(p1), m.Match(p2) - if m1 && m2 { - r1, r2 := revision(p1.OSVersion), revision(p2.OSVersion) - return r1 > r2 - } - return m1 && !m2 -} - -func revision(v string) int { - parts := strings.Split(v, ".") - if len(parts) < 4 { - return 0 - } - r, err := strconv.Atoi(parts[3]) - if err != nil { - return 0 - } - return r -} - -func prefix(v string) string { - parts := strings.Split(v, ".") - if len(parts) < 4 { - return v - } - return strings.Join(parts[0:3], ".") -} - // Default returns the current platform's default platform specification. func Default() MatchComparer { return Only(DefaultSpec()) diff --git a/vendor/github.com/containerd/platforms/platform_compat_windows.go b/vendor/github.com/containerd/platforms/platform_windows_compat.go similarity index 58% rename from vendor/github.com/containerd/platforms/platform_compat_windows.go rename to vendor/github.com/containerd/platforms/platform_windows_compat.go index 89e66f0c09..7f3d9966bc 100644 --- a/vendor/github.com/containerd/platforms/platform_compat_windows.go +++ b/vendor/github.com/containerd/platforms/platform_windows_compat.go @@ -16,9 +16,16 @@ package platforms -// osVersion is a wrapper for Windows version information +import ( + "strconv" + "strings" + + specs "github.com/opencontainers/image-spec/specs-go/v1" +) + +// windowsOSVersion is a wrapper for Windows version information // https://msdn.microsoft.com/en-us/library/windows/desktop/ms724439(v=vs.85).aspx -type osVersion struct { +type windowsOSVersion struct { Version uint32 MajorVersion uint8 MinorVersion uint8 @@ -55,7 +62,7 @@ var compatLTSCReleases = []uint16{ // Every release after WS 2022 will support the previous ltsc // container image. Stable ABI is in preview mode for windows 11 client. // Refer: https://learn.microsoft.com/en-us/virtualization/windowscontainers/deploy-containers/version-compatibility?tabs=windows-server-2022%2Cwindows-10#windows-server-host-os-compatibility -func checkHostAndContainerCompat(host, ctr osVersion) bool { +func checkWindowsHostAndContainerCompat(host, ctr windowsOSVersion) bool { // check major minor versions of host and guest if host.MajorVersion != ctr.MajorVersion || host.MinorVersion != ctr.MinorVersion { @@ -76,3 +83,74 @@ func checkHostAndContainerCompat(host, ctr osVersion) bool { } return ctr.Build >= supportedLtscRelease && ctr.Build <= host.Build } + +func getWindowsOSVersion(osVersionPrefix string) windowsOSVersion { + if strings.Count(osVersionPrefix, ".") < 2 { + return windowsOSVersion{} + } + + major, extra, _ := strings.Cut(osVersionPrefix, ".") + minor, extra, _ := strings.Cut(extra, ".") + build, _, _ := strings.Cut(extra, ".") + + majorVersion, err := strconv.ParseUint(major, 10, 8) + if err != nil { + return windowsOSVersion{} + } + + minorVersion, err := strconv.ParseUint(minor, 10, 8) + if err != nil { + return windowsOSVersion{} + } + buildNumber, err := strconv.ParseUint(build, 10, 16) + if err != nil { + return windowsOSVersion{} + } + + return windowsOSVersion{ + MajorVersion: uint8(majorVersion), + MinorVersion: uint8(minorVersion), + Build: uint16(buildNumber), + } +} + +func winRevision(v string) int { + parts := strings.Split(v, ".") + if len(parts) < 4 { + return 0 + } + r, err := strconv.Atoi(parts[3]) + if err != nil { + return 0 + } + return r +} + +type windowsVersionMatcher struct { + windowsOSVersion +} + +func (m windowsVersionMatcher) Match(v string) bool { + if m.isEmpty() || v == "" { + return true + } + osv := getWindowsOSVersion(v) + return checkWindowsHostAndContainerCompat(m.windowsOSVersion, osv) +} + +func (m windowsVersionMatcher) isEmpty() bool { + return m.MajorVersion == 0 && m.MinorVersion == 0 && m.Build == 0 +} + +type windowsMatchComparer struct { + Matcher +} + +func (c *windowsMatchComparer) Less(p1, p2 specs.Platform) bool { + m1, m2 := c.Match(p1), c.Match(p2) + if m1 && m2 { + r1, r2 := winRevision(p1.OSVersion), winRevision(p2.OSVersion) + return r1 > r2 + } + return m1 && !m2 +} diff --git a/vendor/github.com/containerd/platforms/platforms.go b/vendor/github.com/containerd/platforms/platforms.go index 1bbbdb91db..14d65abd4f 100644 --- a/vendor/github.com/containerd/platforms/platforms.go +++ b/vendor/github.com/containerd/platforms/platforms.go @@ -121,7 +121,7 @@ import ( ) var ( - specifierRe = regexp.MustCompile(`^[A-Za-z0-9_-]+$`) + specifierRe = regexp.MustCompile(`^[A-Za-z0-9_.-]+$`) osAndVersionRe = regexp.MustCompile(`^([A-Za-z0-9_-]+)(?:\(([A-Za-z0-9_.-]*)\))?$`) ) @@ -144,18 +144,51 @@ type Matcher interface { // // Applications should opt to use `Match` over directly parsing specifiers. func NewMatcher(platform specs.Platform) Matcher { - return newDefaultMatcher(platform) + m := &matcher{ + Platform: Normalize(platform), + } + + if platform.OS == "windows" { + m.osvM = &windowsVersionMatcher{ + windowsOSVersion: getWindowsOSVersion(platform.OSVersion), + } + // In prior versions, on windows, the returned matcher implements a + // MatchComprarer interface. + // This preserves that behavior for backwards compatibility. + // + // TODO: This isn't actually used in this package, except for a test case, + // which may have been an unintended side of some refactor. + // It was likely intended to be used in `Ordered` but it is not since + // `Less` that is implemented here ends up getting masked due to wrapping. + if runtime.GOOS == "windows" { + return &windowsMatchComparer{m} + } + } + return m +} + +type osVerMatcher interface { + Match(string) bool } type matcher struct { specs.Platform + osvM osVerMatcher } func (m *matcher) Match(platform specs.Platform) bool { normalized := Normalize(platform) return m.OS == normalized.OS && m.Architecture == normalized.Architecture && - m.Variant == normalized.Variant + m.Variant == normalized.Variant && + m.matchOSVersion(platform) +} + +func (m *matcher) matchOSVersion(platform specs.Platform) bool { + if m.osvM != nil { + return m.osvM.Match(platform.OSVersion) + } + return true } func (m *matcher) String() string { diff --git a/vendor/github.com/containerd/plugin/.golangci.yml b/vendor/github.com/containerd/plugin/.golangci.yml new file mode 100644 index 0000000000..d574fe11d7 --- /dev/null +++ b/vendor/github.com/containerd/plugin/.golangci.yml @@ -0,0 +1,32 @@ +linters: + enable: + - copyloopvar + - gofmt + - goimports + - gosec + - ineffassign + - misspell + - nolintlint + - revive + - staticcheck + - tenv # Detects using os.Setenv instead of t.Setenv since Go 1.17 + - unconvert + - unused + - govet + - dupword # Checks for duplicate words in the source code + disable: + - errcheck + +run: + timeout: 5m + +issues: + exclude-dirs: + - api + - cluster + - design + - docs + - docs/man + - releases + - reports + - test # e2e scripts diff --git a/vendor/github.com/containerd/plugin/LICENSE b/vendor/github.com/containerd/plugin/LICENSE new file mode 100644 index 0000000000..584149b6ee --- /dev/null +++ b/vendor/github.com/containerd/plugin/LICENSE @@ -0,0 +1,191 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + 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 + + https://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. diff --git a/vendor/github.com/containerd/plugin/README.md b/vendor/github.com/containerd/plugin/README.md new file mode 100644 index 0000000000..eb1684f68a --- /dev/null +++ b/vendor/github.com/containerd/plugin/README.md @@ -0,0 +1,19 @@ +# plugin + +A Go package providing a common plugin interface across containerd repositories. + +This package is intended to be imported by the main containerd repository as well as plugin implementations. +By sharing a common implementations, plugins can register themselves without needing to import the main containerd repository. +This plugin is intended to provide an interface and common functionality, but is not intended to define plugin types used by containerd. +Plugins should copy plugin type strings to avoid creating unintended depdenencies. + +## Project details + +**plugin** is a containerd sub-project, licensed under the [Apache 2.0 license](./LICENSE). +As a containerd sub-project, you will find the: + * [Project governance](https://github.com/containerd/project/blob/main/GOVERNANCE.md), + * [Maintainers](https://github.com/containerd/project/blob/main/MAINTAINERS), + * and [Contributing guidelines](https://github.com/containerd/project/blob/main/CONTRIBUTING.md) + +information in our [`containerd/project`](https://github.com/containerd/project) repository. + diff --git a/vendor/github.com/containerd/containerd/plugin/context.go b/vendor/github.com/containerd/plugin/context.go similarity index 56% rename from vendor/github.com/containerd/containerd/plugin/context.go rename to vendor/github.com/containerd/plugin/context.go index 370508d28d..3b985ab75e 100644 --- a/vendor/github.com/containerd/containerd/plugin/context.go +++ b/vendor/github.com/containerd/plugin/context.go @@ -19,38 +19,31 @@ package plugin import ( "context" "fmt" - "path/filepath" - ocispec "github.com/opencontainers/image-spec/specs-go/v1" - - "github.com/containerd/containerd/errdefs" - "github.com/containerd/containerd/events/exchange" + imagespec "github.com/opencontainers/image-spec/specs-go/v1" ) // InitContext is used for plugin initialization type InitContext struct { Context context.Context - Root string - State string + Properties map[string]string Config interface{} - Address string - TTRPCAddress string RegisterReadiness func() func() - // deprecated: will be removed in 2.0, use plugin.EventType - Events *exchange.Exchange - - Meta *Meta // plugins can fill in metadata at init. + // Meta is metadata plugins can fill in at init + Meta *Meta plugins *Set } // NewContext returns a new plugin InitContext -func NewContext(ctx context.Context, r *Registration, plugins *Set, root, state string) *InitContext { +func NewContext(ctx context.Context, plugins *Set, properties map[string]string) *InitContext { + if properties == nil { + properties = map[string]string{} + } return &InitContext{ - Context: ctx, - Root: filepath.Join(root, r.URI()), - State: filepath.Join(state, r.URI()), + Context: ctx, + Properties: properties, Meta: &Meta{ Exports: map[string]string{}, }, @@ -58,31 +51,26 @@ func NewContext(ctx context.Context, r *Registration, plugins *Set, root, state } } -// Get returns the first plugin by its type -func (i *InitContext) Get(t Type) (interface{}, error) { - return i.plugins.Get(t) -} - // Meta contains information gathered from the registration and initialization // process. type Meta struct { - Platforms []ocispec.Platform // platforms supported by plugin - Exports map[string]string // values exported by plugin - Capabilities []string // feature switches for plugin + Platforms []imagespec.Platform // platforms supported by plugin + Exports map[string]string // values exported by plugin + Capabilities []string // feature switches for plugin } // Plugin represents an initialized plugin, used with an init context. type Plugin struct { - Registration *Registration // registration, as initialized - Config interface{} // config, as initialized - Meta *Meta + Registration Registration // registration, as initialized + Config interface{} // config, as initialized + Meta Meta instance interface{} err error // will be set if there was an error initializing the plugin } // Err returns the errors during initialization. -// returns nil if not error was encountered +// returns nil if no error was encountered func (p *Plugin) Err() error { return p.err } @@ -119,32 +107,20 @@ func (ps *Set) Add(p *Plugin) error { } else if _, idok := byID[p.Registration.ID]; !idok { byID[p.Registration.ID] = p } else { - return fmt.Errorf("plugin %v already initialized: %w", p.Registration.URI(), errdefs.ErrAlreadyExists) + return fmt.Errorf("plugin add failed for %s: %w", p.Registration.URI(), ErrPluginInitialized) } ps.ordered = append(ps.ordered, p) return nil } -// Get returns the first plugin by its type -func (ps *Set) Get(t Type) (interface{}, error) { - for _, v := range ps.byTypeAndID[t] { - return v.Instance() - } - return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) -} - -// GetByID returns the plugin of the given type and ID -func (ps *Set) GetByID(t Type, id string) (*Plugin, error) { - typSet, ok := ps.byTypeAndID[t] - if !ok || len(typSet) == 0 { - return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) - } - p, ok := typSet[id] +// Get returns the plugin with the given type and id +func (ps *Set) Get(t Type, id string) *Plugin { + p, ok := ps.byTypeAndID[t] if !ok { - return nil, fmt.Errorf("no plugins registered for %s %q: %w", t, id, errdefs.ErrNotFound) + return nil } - return p, nil + return p[id] } // GetAll returns all initialized plugins @@ -152,6 +128,37 @@ func (ps *Set) GetAll() []*Plugin { return ps.ordered } +// GetSingle returns a plugin instance of the given type when only a single instance +// of that type is expected. Throws an ErrPluginNotFound if no plugin is found and +// ErrPluginMultipleInstances when multiple instances are found. +// Since plugins are not ordered, if multiple instances is suported then +// GetByType should be used. If only one is expected, then to switch plugins, +// disable or remove the unused plugins of the same type. +func (i *InitContext) GetSingle(t Type) (interface{}, error) { + var ( + found bool + instance interface{} + ) + for _, v := range i.plugins.byTypeAndID[t] { + i, err := v.Instance() + if err != nil { + if IsSkipPlugin(err) { + continue + } + return i, err + } + if found { + return nil, fmt.Errorf("multiple plugins registered for %s: %w", t, ErrPluginMultipleInstances) + } + instance = i + found = true + } + if !found { + return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound) + } + return instance, nil +} + // Plugins returns plugin set func (i *InitContext) Plugins() *Set { return i.plugins @@ -164,23 +171,29 @@ func (i *InitContext) GetAll() []*Plugin { // GetByID returns the plugin of the given type and ID func (i *InitContext) GetByID(t Type, id string) (interface{}, error) { - ps, err := i.GetByType(t) - if err != nil { - return nil, err - } - p, ok := ps[id] - if !ok { - return nil, fmt.Errorf("no %s plugins with id %s: %w", t, id, errdefs.ErrNotFound) + p := i.plugins.Get(t, id) + if p == nil { + return nil, fmt.Errorf("no plugins registered for %s.%s: %w", t, id, ErrPluginNotFound) } return p.Instance() } // GetByType returns all plugins with the specific type. -func (i *InitContext) GetByType(t Type) (map[string]*Plugin, error) { - p, ok := i.plugins.byTypeAndID[t] - if !ok { - return nil, fmt.Errorf("no plugins registered for %s: %w", t, errdefs.ErrNotFound) +func (i *InitContext) GetByType(t Type) (map[string]interface{}, error) { + pi := map[string]interface{}{} + for id, p := range i.plugins.byTypeAndID[t] { + i, err := p.Instance() + if err != nil { + if IsSkipPlugin(err) { + continue + } + return nil, err + } + pi[id] = i + } + if len(pi) == 0 { + return nil, fmt.Errorf("no plugins registered for %s: %w", t, ErrPluginNotFound) } - return p, nil + return pi, nil } diff --git a/vendor/github.com/containerd/plugin/plugin.go b/vendor/github.com/containerd/plugin/plugin.go new file mode 100644 index 0000000000..f7899e184f --- /dev/null +++ b/vendor/github.com/containerd/plugin/plugin.go @@ -0,0 +1,178 @@ +/* + 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 plugin + +import ( + "context" + "errors" + "fmt" +) + +var ( + // ErrNoType is returned when no type is specified + ErrNoType = errors.New("plugin: no type") + // ErrNoPluginID is returned when no id is specified + ErrNoPluginID = errors.New("plugin: no id") + // ErrIDRegistered is returned when a duplicate id is already registered + ErrIDRegistered = errors.New("plugin: id already registered") + // ErrSkipPlugin is used when a plugin is not initialized and should not be loaded, + // this allows the plugin loader differentiate between a plugin which is configured + // not to load and one that fails to load. + ErrSkipPlugin = errors.New("skip plugin") + // ErrPluginInitialized is used when a plugin is already initialized + ErrPluginInitialized = errors.New("plugin: already initialized") + // ErrPluginNotFound is used when a plugin is looked up but not found + ErrPluginNotFound = errors.New("plugin: not found") + // ErrPluginMultipleInstances is used when a plugin is expected a single instance but has multiple + ErrPluginMultipleInstances = errors.New("plugin: multiple instances") + + // ErrInvalidRequires will be thrown if the requirements for a plugin are + // defined in an invalid manner. + ErrInvalidRequires = errors.New("invalid requires") +) + +// IsSkipPlugin returns true if the error is skipping the plugin +func IsSkipPlugin(err error) bool { + return errors.Is(err, ErrSkipPlugin) +} + +// Type is the type of the plugin +type Type string + +func (t Type) String() string { return string(t) } + +// Registration contains information for registering a plugin +type Registration struct { + // Type of the plugin + Type Type + // ID of the plugin + ID string + // Config specific to the plugin + Config interface{} + // Requires is a list of plugins that the registered plugin requires to be available + Requires []Type + + // InitFn is called when initializing a plugin. The registration and + // context are passed in. The init function may modify the registration to + // add exports, capabilities and platform support declarations. + InitFn func(*InitContext) (interface{}, error) + + // ConfigMigration allows a plugin to migrate configurations from an older + // version to handle plugin renames or moving of features from one plugin + // to another in a later version. + // The configuration map is keyed off the plugin name and the value + // is the configuration for that objects, with the structure defined + // for the plugin. No validation is done on the value before performing + // the migration. + ConfigMigration func(context.Context, int, map[string]interface{}) error +} + +// Init the registered plugin +func (r Registration) Init(ic *InitContext) *Plugin { + p, err := r.InitFn(ic) + return &Plugin{ + Registration: r, + Config: ic.Config, + Meta: *ic.Meta, + instance: p, + err: err, + } +} + +// URI returns the full plugin URI +func (r *Registration) URI() string { + return r.Type.String() + "." + r.ID +} + +// DisableFilter filters out disabled plugins +type DisableFilter func(r *Registration) bool + +// Registry is list of registrations which can be registered to and +// produce a filtered and ordered output. +// The Registry itself is immutable and the list will be copied +// and appeneded to a new registry when new items are registered. +type Registry []*Registration + +// Graph computes the ordered list of registrations based on their dependencies, +// filtering out any plugins which match the provided filter. +func (registry Registry) Graph(filter DisableFilter) []Registration { + disabled := map[*Registration]bool{} + for _, r := range registry { + if filter(r) { + disabled[r] = true + } + } + + ordered := make([]Registration, 0, len(registry)-len(disabled)) + added := map[*Registration]bool{} + for _, r := range registry { + if disabled[r] { + continue + } + children(r, registry, added, disabled, &ordered) + if !added[r] { + ordered = append(ordered, *r) + added[r] = true + } + } + return ordered +} + +func children(reg *Registration, registry []*Registration, added, disabled map[*Registration]bool, ordered *[]Registration) { + for _, t := range reg.Requires { + for _, r := range registry { + if !disabled[r] && r.URI() != reg.URI() && (t == "*" || r.Type == t) { + children(r, registry, added, disabled, ordered) + if !added[r] { + *ordered = append(*ordered, *r) + added[r] = true + } + } + } + } +} + +// Register adds the registration to a Registry and returns the +// updated Registry, panicking if registration could not succeed. +func (registry Registry) Register(r *Registration) Registry { + if r.Type == "" { + panic(ErrNoType) + } + if r.ID == "" { + panic(ErrNoPluginID) + } + if err := checkUnique(registry, r); err != nil { + panic(err) + } + + for _, requires := range r.Requires { + if requires == "*" && len(r.Requires) != 1 { + panic(ErrInvalidRequires) + } + } + + return append(registry, r) +} + +func checkUnique(registry Registry, r *Registration) error { + for _, registered := range registry { + if r.URI() == registered.URI() { + return fmt.Errorf("%s: %w", r.URI(), ErrIDRegistered) + } + } + return nil +} diff --git a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go index 0ca6fd75f2..ba650b4d1d 100644 --- a/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go +++ b/vendor/github.com/containerd/stargz-snapshotter/estargz/testutil.go @@ -26,12 +26,13 @@ import ( "archive/tar" "bytes" "compress/gzip" + "crypto/rand" "crypto/sha256" "encoding/json" "errors" "fmt" "io" - "math/rand" + "math/big" "os" "path/filepath" "reflect" @@ -45,10 +46,6 @@ import ( digest "github.com/opencontainers/go-digest" ) -func init() { - rand.Seed(time.Now().UnixNano()) -} - // TestingController is Compression with some helper methods necessary for testing. type TestingController interface { Compression @@ -920,9 +917,11 @@ func checkVerifyInvalidTOCEntryFail(filename string) check { } if sampleEntry == nil { t.Fatalf("TOC must contain at least one regfile or chunk entry other than the rewrite target") + return } if targetEntry == nil { t.Fatalf("rewrite target not found") + return } targetEntry.Offset = sampleEntry.Offset }, @@ -2291,7 +2290,11 @@ var runes = []rune("1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWX func randomContents(n int) string { b := make([]rune, n) for i := range b { - b[i] = runes[rand.Intn(len(runes))] + bi, err := rand.Int(rand.Reader, big.NewInt(int64(len(runes)))) + if err != nil { + panic(err) + } + b[i] = runes[int(bi.Int64())] } return string(b) } diff --git a/vendor/github.com/moby/buildkit/api/services/control/control.pb.go b/vendor/github.com/moby/buildkit/api/services/control/control.pb.go index ab0f174f89..bf18f8f5cc 100644 --- a/vendor/github.com/moby/buildkit/api/services/control/control.pb.go +++ b/vendor/github.com/moby/buildkit/api/services/control/control.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/api/services/control/control.proto diff --git a/vendor/github.com/moby/buildkit/api/types/worker.pb.go b/vendor/github.com/moby/buildkit/api/types/worker.pb.go index e7a5ddd06e..c4065f6391 100644 --- a/vendor/github.com/moby/buildkit/api/types/worker.pb.go +++ b/vendor/github.com/moby/buildkit/api/types/worker.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/api/types/worker.proto diff --git a/vendor/github.com/moby/buildkit/cache/blobs.go b/vendor/github.com/moby/buildkit/cache/blobs.go index c3993db8d8..1736eb8877 100644 --- a/vendor/github.com/moby/buildkit/cache/blobs.go +++ b/vendor/github.com/moby/buildkit/cache/blobs.go @@ -7,11 +7,11 @@ import ( "os" "strconv" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/diff/walking" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/plugins/diff/walking" "github.com/moby/buildkit/session" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/compression" diff --git a/vendor/github.com/moby/buildkit/cache/blobs_linux.go b/vendor/github.com/moby/buildkit/cache/blobs_linux.go index 2231373ea7..1b70d1089d 100644 --- a/vendor/github.com/moby/buildkit/cache/blobs_linux.go +++ b/vendor/github.com/moby/buildkit/cache/blobs_linux.go @@ -7,9 +7,9 @@ import ( "context" "io" - "github.com/containerd/containerd/content" - labelspkg "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/mount" + labelspkg "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/compression" diff --git a/vendor/github.com/moby/buildkit/cache/blobs_nolinux.go b/vendor/github.com/moby/buildkit/cache/blobs_nolinux.go index da6554e89c..209391c9dc 100644 --- a/vendor/github.com/moby/buildkit/cache/blobs_nolinux.go +++ b/vendor/github.com/moby/buildkit/cache/blobs_nolinux.go @@ -5,7 +5,7 @@ package cache import ( "context" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/moby/buildkit/util/compression" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/cache/compression_nydus.go b/vendor/github.com/moby/buildkit/cache/compression_nydus.go index d15b341ea7..45d1cb1d1e 100644 --- a/vendor/github.com/moby/buildkit/cache/compression_nydus.go +++ b/vendor/github.com/moby/buildkit/cache/compression_nydus.go @@ -7,8 +7,8 @@ import ( "context" "io" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/session" "github.com/moby/buildkit/util/compression" diff --git a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.pb.go b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.pb.go index bc5290e071..a2a41758ef 100644 --- a/vendor/github.com/moby/buildkit/cache/contenthash/checksum.pb.go +++ b/vendor/github.com/moby/buildkit/cache/contenthash/checksum.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/cache/contenthash/checksum.proto diff --git a/vendor/github.com/moby/buildkit/cache/filelist.go b/vendor/github.com/moby/buildkit/cache/filelist.go index 225a520043..8d4f880dda 100644 --- a/vendor/github.com/moby/buildkit/cache/filelist.go +++ b/vendor/github.com/moby/buildkit/cache/filelist.go @@ -9,7 +9,7 @@ import ( "path" "sort" - cdcompression "github.com/containerd/containerd/archive/compression" + cdcompression "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/moby/buildkit/session" ) diff --git a/vendor/github.com/moby/buildkit/cache/manager.go b/vendor/github.com/moby/buildkit/cache/manager.go index c1b3d52ec1..495012b20b 100644 --- a/vendor/github.com/moby/buildkit/cache/manager.go +++ b/vendor/github.com/moby/buildkit/cache/manager.go @@ -8,12 +8,12 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/filters" - "github.com/containerd/containerd/gc" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/filters" + "github.com/containerd/containerd/v2/pkg/gc" + "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/cache/metadata" diff --git a/vendor/github.com/moby/buildkit/cache/migrate_v2.go b/vendor/github.com/moby/buildkit/cache/migrate_v2.go index 327cfd6742..184abb5562 100644 --- a/vendor/github.com/moby/buildkit/cache/migrate_v2.go +++ b/vendor/github.com/moby/buildkit/cache/migrate_v2.go @@ -6,10 +6,10 @@ import ( "os" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/snapshots" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/cache/metadata" "github.com/moby/buildkit/snapshot" diff --git a/vendor/github.com/moby/buildkit/cache/opts.go b/vendor/github.com/moby/buildkit/cache/opts.go index 1f1db6ca61..b2ddbb6e21 100644 --- a/vendor/github.com/moby/buildkit/cache/opts.go +++ b/vendor/github.com/moby/buildkit/cache/opts.go @@ -3,7 +3,7 @@ package cache import ( "fmt" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/moby/buildkit/session" "github.com/moby/buildkit/util/progress" digest "github.com/opencontainers/go-digest" diff --git a/vendor/github.com/moby/buildkit/cache/refs.go b/vendor/github.com/moby/buildkit/cache/refs.go index aa2a47256d..aa2b3f3809 100644 --- a/vendor/github.com/moby/buildkit/cache/refs.go +++ b/vendor/github.com/moby/buildkit/cache/refs.go @@ -10,12 +10,12 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/docker/docker/pkg/idtools" "github.com/hashicorp/go-multierror" @@ -655,7 +655,7 @@ func (sr *immutableRef) Clone() ImmutableRef { return sr.clone() } -// layertoDistributable changes the passed in media type to the "distributable" version of the media type. +// layerToDistributable changes the passed in media type to the "distributable" version of the media type. func layerToDistributable(mt string) string { if !images.IsNonDistributable(mt) { // Layer is already a distributable media type (or this is not even a layer). diff --git a/vendor/github.com/moby/buildkit/cache/remote.go b/vendor/github.com/moby/buildkit/cache/remote.go index 51d2478971..fa84b1c00e 100644 --- a/vendor/github.com/moby/buildkit/cache/remote.go +++ b/vendor/github.com/moby/buildkit/cache/remote.go @@ -7,8 +7,8 @@ import ( "net/url" "strings" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/reference" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/cache/config" "github.com/moby/buildkit/session" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/export.go b/vendor/github.com/moby/buildkit/cache/remotecache/export.go index 64347eb086..58b0d5a3bc 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/export.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/export.go @@ -6,8 +6,8 @@ import ( "encoding/json" "fmt" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" v1 "github.com/moby/buildkit/cache/remotecache/v1" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/gha/gha.go b/vendor/github.com/moby/buildkit/cache/remotecache/gha/gha.go index 17c61ef3fe..bbc92a217d 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/gha/gha.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/gha/gha.go @@ -10,8 +10,8 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/labels" "github.com/moby/buildkit/cache/remotecache" v1 "github.com/moby/buildkit/cache/remotecache/v1" "github.com/moby/buildkit/session" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/import.go b/vendor/github.com/moby/buildkit/cache/remotecache/import.go index 99b9695f86..e8fff77c58 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/import.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/import.go @@ -8,9 +8,9 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" v1 "github.com/moby/buildkit/cache/remotecache/v1" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/inline/inline.go b/vendor/github.com/moby/buildkit/cache/remotecache/inline/inline.go index 039348022d..5ac9fdcd43 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/inline/inline.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/inline/inline.go @@ -5,7 +5,7 @@ import ( "encoding/json" "slices" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/pkg/labels" "github.com/moby/buildkit/cache/remotecache" v1 "github.com/moby/buildkit/cache/remotecache/v1" "github.com/moby/buildkit/session" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go b/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go index 9508427637..9b999dcbe8 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/local/local.go @@ -5,7 +5,7 @@ import ( "strconv" "time" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/moby/buildkit/cache/remotecache" "github.com/moby/buildkit/session" sessioncontent "github.com/moby/buildkit/session/content" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go b/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go index a6f89bbaf7..111af04583 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/registry/registry.go @@ -5,9 +5,9 @@ import ( "maps" "strconv" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/distribution/reference" "github.com/moby/buildkit/cache/remotecache" "github.com/moby/buildkit/session" diff --git a/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go b/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go index 87744d9ec7..dbca2961b6 100644 --- a/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go +++ b/vendor/github.com/moby/buildkit/cache/remotecache/v1/chains.go @@ -6,7 +6,7 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver" digest "github.com/opencontainers/go-digest" diff --git a/vendor/github.com/moby/buildkit/client/client.go b/vendor/github.com/moby/buildkit/client/client.go index 874b386e2f..2ca45ca5f0 100644 --- a/vendor/github.com/moby/buildkit/client/client.go +++ b/vendor/github.com/moby/buildkit/client/client.go @@ -10,7 +10,7 @@ import ( "time" contentapi "github.com/containerd/containerd/api/services/content/v1" - "github.com/containerd/containerd/defaults" + "github.com/containerd/containerd/v2/defaults" controlapi "github.com/moby/buildkit/api/services/control" "github.com/moby/buildkit/client/connhelper" "github.com/moby/buildkit/session" diff --git a/vendor/github.com/moby/buildkit/client/llb/fileop.go b/vendor/github.com/moby/buildkit/client/llb/fileop.go index 1fa7935769..689eda0b0d 100644 --- a/vendor/github.com/moby/buildkit/client/llb/fileop.go +++ b/vendor/github.com/moby/buildkit/client/llb/fileop.go @@ -85,6 +85,13 @@ func (fa *FileAction) Mkfile(p string, m os.FileMode, dt []byte, opt ...MkfileOp return a } +// Symlink creates a symlink at `newpath` that points to `oldpath` +func (fa *FileAction) Symlink(oldpath, newpath string, opt ...SymlinkOption) *FileAction { + a := Symlink(oldpath, newpath, opt...) + a.prev = fa + return a +} + func (fa *FileAction) Rm(p string, opt ...RmOption) *FileAction { a := Rm(p, opt...) a.prev = fa @@ -193,6 +200,7 @@ type ChownOption interface { MkdirOption MkfileOption CopyOption + SymlinkOption } type mkdirOptionFunc func(*MkdirInfo) @@ -290,6 +298,10 @@ func (co ChownOpt) SetCopyOption(mi *CopyInfo) { mi.ChownOpt = &co } +func (co ChownOpt) SetSymlinkOption(si *SymlinkInfo) { + si.ChownOpt = &co +} + func (co *ChownOpt) marshal(base pb.InputIndex) *pb.ChownOpt { if co == nil { return nil @@ -337,6 +349,57 @@ func Mkfile(p string, m os.FileMode, dt []byte, opts ...MkfileOption) *FileActio } } +// SymlinkInfo is the modifiable options used to create symlinks +type SymlinkInfo struct { + ChownOpt *ChownOpt + CreatedTime *time.Time +} + +func (si *SymlinkInfo) SetSymlinkOption(si2 *SymlinkInfo) { + *si2 = *si +} + +type SymlinkOption interface { + SetSymlinkOption(*SymlinkInfo) +} + +// Symlink creates a symlink at `newpath` that points to `oldpath` +func Symlink(oldpath, newpath string, opts ...SymlinkOption) *FileAction { + var si SymlinkInfo + for _, o := range opts { + o.SetSymlinkOption(&si) + } + + return &FileAction{ + action: &fileActionSymlink{ + oldpath: oldpath, + newpath: newpath, + info: si, + }, + } +} + +type fileActionSymlink struct { + oldpath string + newpath string + info SymlinkInfo +} + +func (s *fileActionSymlink) addCaps(f *FileOp) { + addCap(&f.constraints, pb.CapFileSymlinkCreate) +} + +func (s *fileActionSymlink) toProtoAction(_ context.Context, _ string, base pb.InputIndex) (pb.IsFileAction, error) { + return &pb.FileAction_Symlink{ + Symlink: &pb.FileActionSymlink{ + Oldpath: s.oldpath, + Newpath: s.newpath, + Owner: s.info.ChownOpt.marshal(base), + Timestamp: marshalTime(s.info.CreatedTime), + }, + }, nil +} + type MkfileOption interface { SetMkfileOption(*MkfileInfo) } @@ -606,6 +669,10 @@ func (c CreatedTime) SetMkfileOption(mi *MkfileInfo) { mi.CreatedTime = (*time.Time)(&c) } +func (c CreatedTime) SetSymlinkOption(si *SymlinkInfo) { + si.CreatedTime = (*time.Time)(&c) +} + func (c CreatedTime) SetCopyOption(mi *CopyInfo) { mi.CreatedTime = (*time.Time)(&c) } diff --git a/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go b/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go index e489ecf471..d5bfb1a469 100644 --- a/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go +++ b/vendor/github.com/moby/buildkit/client/llb/imagemetaresolver/resolver.go @@ -5,8 +5,8 @@ import ( "net/http" "sync" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/containerd/platforms" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/client/llb/sourceresolver" @@ -107,7 +107,7 @@ func (imr *imageMetaResolver) ResolveImageConfig(ctx context.Context, ref string func (imr *imageMetaResolver) key(ref string, platform *ocispecs.Platform) string { if platform != nil { - ref += platforms.Format(*platform) + ref += platforms.FormatAll(*platform) } return ref } diff --git a/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go b/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go index e427f65508..5ed51f4135 100644 --- a/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go +++ b/vendor/github.com/moby/buildkit/client/ociindex/ociindex.go @@ -3,10 +3,12 @@ package ociindex import ( "encoding/json" "io" + "maps" "os" "path" "syscall" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/gofrs/flock" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" @@ -15,6 +17,8 @@ import ( const ( // lockFileSuffix is the suffix of the lock file lockFileSuffix = ".lock" + + annotationImageName = "io.containerd.image.name" ) type StoreIndex struct { @@ -23,6 +27,19 @@ type StoreIndex struct { layoutPath string } +type NameOrTag struct { + isTag bool + value string +} + +func Name(name string) NameOrTag { + return NameOrTag{value: name} +} + +func Tag(tag string) NameOrTag { + return NameOrTag{isTag: true, value: tag} +} + func NewStoreIndex(storePath string) StoreIndex { indexPath := path.Join(storePath, ocispecs.ImageIndexFile) layoutPath := path.Join(storePath, ocispecs.ImageLayoutFile) @@ -61,7 +78,7 @@ func (s StoreIndex) Read() (*ocispecs.Index, error) { return &idx, nil } -func (s StoreIndex) Put(tag string, desc ocispecs.Descriptor) error { +func (s StoreIndex) Put(desc ocispecs.Descriptor, names ...NameOrTag) error { // lock the store to prevent concurrent access lock := flock.New(s.lockPath) locked, err := lock.TryLock() @@ -107,8 +124,19 @@ func (s StoreIndex) Put(tag string, desc ocispecs.Descriptor) error { } setOCIIndexDefaults(&idx) - if err = insertDesc(&idx, desc, tag); err != nil { - return err + + namesp := make([]*NameOrTag, 0, len(names)) + for _, n := range names { + namesp = append(namesp, &n) + } + if len(names) == 0 { + namesp = append(namesp, nil) + } + + for _, name := range namesp { + if err = insertDesc(&idx, desc, name); err != nil { + return err + } } idxData, err = json.Marshal(idx) @@ -130,6 +158,12 @@ func (s StoreIndex) Get(tag string) (*ocispecs.Descriptor, error) { return nil, err } + for _, m := range idx.Manifests { + if t, ok := m.Annotations[annotationImageName]; ok && t == tag { + return &m, nil + } + } + for _, m := range idx.Manifests { if t, ok := m.Annotations[ocispecs.AnnotationRefName]; ok && t == tag { return &m, nil @@ -165,20 +199,34 @@ func setOCIIndexDefaults(index *ocispecs.Index) { // insertDesc puts desc to index with tag. // Existing manifests with the same tag will be removed from the index. -func insertDesc(index *ocispecs.Index, desc ocispecs.Descriptor, tag string) error { +func insertDesc(index *ocispecs.Index, in ocispecs.Descriptor, name *NameOrTag) error { if index == nil { return nil } - if tag != "" { + // make a copy to not modify the input descriptor + desc := in + desc.Annotations = maps.Clone(in.Annotations) + + if name != nil { if desc.Annotations == nil { desc.Annotations = make(map[string]string) } - desc.Annotations[ocispecs.AnnotationRefName] = tag - // remove existing manifests with the same tag + imgName, refName := name.value, name.value + if name.isTag { + imgName = "" + } else { + refName = ociReferenceName(imgName) + } + + if imgName != "" { + desc.Annotations[annotationImageName] = imgName + } + desc.Annotations[ocispecs.AnnotationRefName] = refName + // remove existing manifests with the same tag/name var manifests []ocispecs.Descriptor for _, m := range index.Manifests { - if m.Annotations[ocispecs.AnnotationRefName] != tag { + if m.Annotations[ocispecs.AnnotationRefName] != refName || m.Annotations[annotationImageName] != imgName { manifests = append(manifests, m) } } @@ -187,3 +235,20 @@ func insertDesc(index *ocispecs.Index, desc ocispecs.Descriptor, tag string) err index.Manifests = append(index.Manifests, desc) return nil } + +// ociReferenceName takes the loosely defined reference name same way as +// containerd tar exporter does. +func ociReferenceName(name string) string { + // OCI defines the reference name as only a tag excluding the + // repository. The containerd annotation contains the full image name + // since the tag is insufficient for correctly naming and referring to an + // image + var ociRef string + if spec, err := reference.Parse(name); err == nil { + ociRef = spec.Object + } else { + ociRef = name + } + + return ociRef +} diff --git a/vendor/github.com/moby/buildkit/client/solve.go b/vendor/github.com/moby/buildkit/client/solve.go index df2cd16a5e..efdf9fa9f1 100644 --- a/vendor/github.com/moby/buildkit/client/solve.go +++ b/vendor/github.com/moby/buildkit/client/solve.go @@ -10,8 +10,8 @@ import ( "strings" "time" - "github.com/containerd/containerd/content" - contentlocal "github.com/containerd/containerd/content/local" + "github.com/containerd/containerd/v2/core/content" + contentlocal "github.com/containerd/containerd/v2/plugins/content/local" controlapi "github.com/moby/buildkit/api/services/control" "github.com/moby/buildkit/client/llb" "github.com/moby/buildkit/client/ociindex" @@ -345,7 +345,7 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG } for storePath, tag := range cacheOpt.storesToUpdate { idx := ociindex.NewStoreIndex(storePath) - if err := idx.Put(tag, manifestDesc); err != nil { + if err := idx.Put(manifestDesc, ociindex.Tag(tag)); err != nil { return nil, err } } @@ -360,12 +360,16 @@ func (c *Client) solve(ctx context.Context, def *llb.Definition, runGateway runG return nil, err } for _, storePath := range storesToUpdate { - tag := "latest" + names := []ociindex.NameOrTag{ociindex.Tag("latest")} if t, ok := res.ExporterResponse["image.name"]; ok { - tag = t + inp := strings.Split(t, ",") + names = make([]ociindex.NameOrTag, len(inp)) + for i, n := range inp { + names[i] = ociindex.Name(n) + } } idx := ociindex.NewStoreIndex(storePath) - if err := idx.Put(tag, manifestDesc); err != nil { + if err := idx.Put(manifestDesc, names...); err != nil { return nil, err } } diff --git a/vendor/github.com/moby/buildkit/control/control.go b/vendor/github.com/moby/buildkit/control/control.go index 9f1c4ce670..bc515a5d16 100644 --- a/vendor/github.com/moby/buildkit/control/control.go +++ b/vendor/github.com/moby/buildkit/control/control.go @@ -10,8 +10,8 @@ import ( "time" contentapi "github.com/containerd/containerd/api/services/content/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/services/content/contentserver" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/plugins/services/content/contentserver" "github.com/distribution/reference" "github.com/hashicorp/go-multierror" "github.com/mitchellh/hashstructure/v2" diff --git a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go index 9332d4376e..4022de0a6d 100644 --- a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go +++ b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor.go @@ -14,9 +14,9 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" - "github.com/containerd/containerd" - "github.com/containerd/containerd/cio" - "github.com/containerd/containerd/mount" + ctd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/cio" "github.com/moby/buildkit/executor" "github.com/moby/buildkit/executor/oci" resourcestypes "github.com/moby/buildkit/executor/resources/types" @@ -28,7 +28,7 @@ import ( ) type containerdExecutor struct { - client *containerd.Client + client *ctd.Client root string networkProviders map[pb.NetMode]network.Provider cgroupParent string @@ -62,7 +62,7 @@ type RuntimeInfo struct { } type ExecutorOptions struct { - Client *containerd.Client + Client *ctd.Client Root string CgroupParent string NetworkProviders map[pb.NetMode]network.Provider @@ -168,11 +168,11 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M defer releaseSpec() } - opts := []containerd.NewContainerOpts{ - containerd.WithSpec(spec), + opts := []ctd.NewContainerOpts{ + ctd.WithSpec(spec), } if w.runtime != nil { - opts = append(opts, containerd.WithRuntime(w.runtime.Name, w.runtime.Options)) + opts = append(opts, ctd.WithRuntime(w.runtime.Name, w.runtime.Options)) } container, err := w.client.NewContainer(ctx, id, opts...) if err != nil { @@ -196,7 +196,7 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M return nil, err } if w.runtime != nil && w.runtime.Path != "" { - taskOpts = append(taskOpts, containerd.WithRuntimePath(w.runtime.Path)) + taskOpts = append(taskOpts, ctd.WithRuntimePath(w.runtime.Path)) } task, err := container.NewTask(ctx, cio.NewCreator(cioOpts...), taskOpts...) if err != nil { @@ -204,7 +204,7 @@ func (w *containerdExecutor) Run(ctx context.Context, id string, root executor.M } defer func() { - if _, err1 := task.Delete(context.WithoutCancel(ctx), containerd.WithProcessKill); err == nil && err1 != nil { + if _, err1 := task.Delete(context.WithoutCancel(ctx), ctd.WithProcessKill); err == nil && err1 != nil { err = errors.Wrapf(err1, "failed to delete task %s", id) } }() @@ -241,8 +241,8 @@ func (w *containerdExecutor) Exec(ctx context.Context, id string, process execut if !ok { return errors.Errorf("container %s not found", id) } - var container containerd.Container - var task containerd.Task + var container ctd.Container + var task ctd.Task for { if container == nil { container, _ = w.client.LoadContainer(ctx, id) @@ -252,7 +252,7 @@ func (w *containerdExecutor) Exec(ctx context.Context, id string, process execut } if task != nil { status, _ := task.Status(ctx) - if status.Status == containerd.Running { + if status.Status == ctd.Running { break } } @@ -324,7 +324,7 @@ func fixProcessOutput(process *executor.ProcessInfo) { } } -func (w *containerdExecutor) runProcess(ctx context.Context, p containerd.Process, resize <-chan executor.WinSize, signal <-chan syscall.Signal, validExitCodes []int, started func()) error { +func (w *containerdExecutor) runProcess(ctx context.Context, p ctd.Process, resize <-chan executor.WinSize, signal <-chan syscall.Signal, validExitCodes []int, started func()) error { // Not using `ctx` here because the context passed only affects the statusCh which we // don't want cancelled when ctx.Done is sent. We want to process statusCh on cancel. statusCh, err := p.Wait(context.Background()) @@ -347,7 +347,7 @@ func (w *containerdExecutor) runProcess(ctx context.Context, p containerd.Proces started() } - p.CloseIO(ctx, containerd.WithStdinCloser) + p.CloseIO(ctx, ctd.WithStdinCloser) // handle signals (and resize) in separate go loop so it does not // potentially block the container cancel/exit status loop below. diff --git a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_unix.go b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_unix.go index f1c5e1f1be..10b6fababe 100644 --- a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_unix.go +++ b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_unix.go @@ -7,9 +7,9 @@ import ( "os" "runtime" - "github.com/containerd/containerd" - "github.com/containerd/containerd/mount" - containerdoci "github.com/containerd/containerd/oci" + ctd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/mount" + containerdoci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/executor" @@ -161,20 +161,20 @@ func (w *containerdExecutor) createOCISpec(ctx context.Context, id, resolvConf, return spec, releaseAll, nil } -func (d *containerState) getTaskOpts() ([]containerd.NewTaskOpts, error) { - rootfs := containerd.WithRootFS([]mount.Mount{{ +func (d *containerState) getTaskOpts() ([]ctd.NewTaskOpts, error) { + rootfs := ctd.WithRootFS([]mount.Mount{{ Source: d.rootfsPath, Type: "bind", Options: []string{"rbind"}, }}) if runtime.GOOS == "freebsd" { - rootfs = containerd.WithRootFS([]mount.Mount{{ + rootfs = ctd.WithRootFS([]mount.Mount{{ Source: d.rootfsPath, Type: "nullfs", Options: []string{}, }}) } - return []containerd.NewTaskOpts{rootfs}, nil + return []ctd.NewTaskOpts{rootfs}, nil } func setArgs(spec *specs.Process, args []string) { diff --git a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_windows.go b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_windows.go index 1155a1b0e3..14f0cf444c 100644 --- a/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_windows.go +++ b/vendor/github.com/moby/buildkit/executor/containerdexecutor/executor_windows.go @@ -5,8 +5,8 @@ import ( "os" "strings" - "github.com/containerd/containerd" - containerdoci "github.com/containerd/containerd/oci" + ctd "github.com/containerd/containerd/v2/client" + containerdoci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/executor" @@ -97,8 +97,8 @@ func (w *containerdExecutor) createOCISpec(ctx context.Context, id, _, _ string, return spec, releaseAll, nil } -func (d *containerState) getTaskOpts() ([]containerd.NewTaskOpts, error) { - return []containerd.NewTaskOpts{containerd.WithRootFS(d.rootMounts)}, nil +func (d *containerState) getTaskOpts() ([]ctd.NewTaskOpts, error) { + return []ctd.NewTaskOpts{ctd.WithRootFS(d.rootMounts)}, nil } func setArgs(spec *specs.Process, args []string) { diff --git a/vendor/github.com/moby/buildkit/executor/executor.go b/vendor/github.com/moby/buildkit/executor/executor.go index 711e84f222..9902392084 100644 --- a/vendor/github.com/moby/buildkit/executor/executor.go +++ b/vendor/github.com/moby/buildkit/executor/executor.go @@ -6,7 +6,7 @@ import ( "net" "syscall" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/docker/docker/pkg/idtools" resourcestypes "github.com/moby/buildkit/executor/resources/types" "github.com/moby/buildkit/solver/pb" diff --git a/vendor/github.com/moby/buildkit/executor/oci/mounts.go b/vendor/github.com/moby/buildkit/executor/oci/mounts.go index 39e1da1537..5e6b286b8f 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/mounts.go +++ b/vendor/github.com/moby/buildkit/executor/oci/mounts.go @@ -5,8 +5,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" specs "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec.go b/vendor/github.com/moby/buildkit/executor/oci/spec.go index 4a7a865216..fe0b03c4a1 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/spec.go +++ b/vendor/github.com/moby/buildkit/executor/oci/spec.go @@ -9,10 +9,10 @@ import ( "strings" "sync" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/namespaces" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/docker/docker/pkg/idtools" "github.com/mitchellh/hashstructure/v2" "github.com/moby/buildkit/executor" diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_darwin.go b/vendor/github.com/moby/buildkit/executor/oci/spec_darwin.go index fbcaff1912..c2658ecb9e 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/spec_darwin.go +++ b/vendor/github.com/moby/buildkit/executor/oci/spec_darwin.go @@ -1,8 +1,8 @@ package oci import ( - "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/continuity/fs" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/solver/pb" diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_freebsd.go b/vendor/github.com/moby/buildkit/executor/oci/spec_freebsd.go index 2103748252..73cbe7ec79 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/spec_freebsd.go +++ b/vendor/github.com/moby/buildkit/executor/oci/spec_freebsd.go @@ -1,8 +1,8 @@ package oci import ( - "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/continuity/fs" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/solver/pb" diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go b/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go index 06215e9447..9ee59fc85a 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go +++ b/vendor/github.com/moby/buildkit/executor/oci/spec_linux.go @@ -8,11 +8,11 @@ import ( "strings" "sync" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/apparmor" - cdseccomp "github.com/containerd/containerd/pkg/seccomp" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/apparmor" + "github.com/containerd/containerd/v2/pkg/oci" + cdseccomp "github.com/containerd/containerd/v2/pkg/seccomp" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" "github.com/docker/docker/profiles/seccomp" diff --git a/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go b/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go index c02e98dea5..d3059c3034 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go +++ b/vendor/github.com/moby/buildkit/executor/oci/spec_windows.go @@ -9,9 +9,9 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/solver/pb" diff --git a/vendor/github.com/moby/buildkit/executor/oci/user.go b/vendor/github.com/moby/buildkit/executor/oci/user.go index 9d0b81621a..ad10f213f5 100644 --- a/vendor/github.com/moby/buildkit/executor/oci/user.go +++ b/vendor/github.com/moby/buildkit/executor/oci/user.go @@ -6,8 +6,8 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/containers" - containerdoci "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/containers" + containerdoci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" "github.com/moby/sys/user" specs "github.com/opencontainers/runtime-spec/specs-go" diff --git a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go index 3f401eb230..f284c90cd1 100644 --- a/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go +++ b/vendor/github.com/moby/buildkit/executor/runcexecutor/executor.go @@ -19,8 +19,8 @@ import ( "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/trace" - "github.com/containerd/containerd/mount" - containerdoci "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/core/mount" + containerdoci "github.com/containerd/containerd/v2/pkg/oci" "github.com/containerd/continuity/fs" runc "github.com/containerd/go-runc" "github.com/docker/docker/pkg/idtools" diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/annotations.go b/vendor/github.com/moby/buildkit/exporter/containerimage/annotations.go index 5973f628ad..1bf10f6c15 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/annotations.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/annotations.go @@ -71,7 +71,7 @@ func (ag AnnotationsGroup) Platform(p *ocispecs.Platform) *Annotations { ps := []string{""} if p != nil { - ps = append(ps, platforms.Format(*p)) + ps = append(ps, platforms.FormatAll(*p)) } for _, a := range ag { diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/export.go b/vendor/github.com/moby/buildkit/exporter/containerimage/export.go index 02bd91b0c0..7c4136b538 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/export.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/export.go @@ -10,13 +10,13 @@ import ( "strconv" "strings" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/pkg/epoch" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/rootfs" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/pkg/epoch" + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/rootfs" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/platforms" "github.com/moby/buildkit/cache" diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/annotations.go b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/annotations.go index 37f1b205d1..a9b74d6b96 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/annotations.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/annotations.go @@ -49,7 +49,7 @@ func (k AnnotationKey) PlatformString() string { if k.Platform == nil { return "" } - return platforms.Format(*k.Platform) + return platforms.FormatAll(*k.Platform) } func AnnotationIndexKey(key string) string { diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/keys.go b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/keys.go index 722f099cf0..8eb2064e11 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/keys.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/keys.go @@ -44,6 +44,9 @@ var ( // Value: bool OptKeyOCITypes ImageExporterOptKey = "oci-mediatypes" + // Use OCI artifact format for the attestation manifest. + OptKeyOCIArtifact ImageExporterOptKey = "oci-artifact" + // Force attestation to be attached. // Value: bool OptKeyForceInlineAttestations ImageExporterOptKey = "attestation-inline" diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/parse.go b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/parse.go index bd6222338e..cd2256b566 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/parse.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/exptypes/parse.go @@ -53,7 +53,7 @@ func ParsePlatforms(meta map[string][]byte) (Platforms, error) { } } p = platforms.Normalize(p) - pk := platforms.Format(p) + pk := platforms.FormatAll(p) ps := Platforms{ Platforms: []Platform{{ID: pk, Platform: p}}, } diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/opts.go b/vendor/github.com/moby/buildkit/exporter/containerimage/opts.go index 50ae5de311..1ccadbd946 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/opts.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/opts.go @@ -17,6 +17,7 @@ type ImageCommitOpts struct { ImageName string RefCfg cacheconfig.RefConfig OCITypes bool + OCIArtifact bool Annotations AnnotationsGroup Epoch *time.Time @@ -49,6 +50,8 @@ func (c *ImageCommitOpts) Load(ctx context.Context, opt map[string]string) (map[ c.ImageName = v case exptypes.OptKeyOCITypes: err = parseBoolWithDefault(&c.OCITypes, k, v, true) + case exptypes.OptKeyOCIArtifact: + err = parseBool(&c.OCIArtifact, k, v) case exptypes.OptKeyForceInlineAttestations: err = parseBool(&c.ForceInlineAttestations, k, v) case exptypes.OptKeyPreferNondistLayers: @@ -67,6 +70,9 @@ func (c *ImageCommitOpts) Load(ctx context.Context, opt map[string]string) (map[ if c.RefCfg.Compression.Type.OnlySupportOCITypes() { c.EnableOCITypes(ctx, c.RefCfg.Compression.Type.String()) } + if c.OCIArtifact && !c.OCITypes { + c.EnableOCITypes(ctx, "oci-artifact") + } c.Annotations = c.Annotations.Merge(as) diff --git a/vendor/github.com/moby/buildkit/exporter/containerimage/writer.go b/vendor/github.com/moby/buildkit/exporter/containerimage/writer.go index 4e3e678fd7..d3bbd3874c 100644 --- a/vendor/github.com/moby/buildkit/exporter/containerimage/writer.go +++ b/vendor/github.com/moby/buildkit/exporter/containerimage/writer.go @@ -10,10 +10,10 @@ import ( "strings" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" + "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/pkg/labels" "github.com/containerd/platforms" intoto "github.com/in-toto/in-toto-golang/in_toto" "github.com/moby/buildkit/cache" @@ -46,6 +46,8 @@ import ( "golang.org/x/sync/errgroup" ) +const attestationManifestArtifactType = "application/vnd.docker.attestation.manifest.v1+json" + type WriterOpt struct { Snapshotter snapshot.Snapshotter ContentStore content.Store @@ -312,7 +314,7 @@ func (ic *ImageWriter) Commit(ctx context.Context, inp *exporter.Source, session return nil, err } - desc, err := ic.commitAttestationsManifest(ctx, opts, desc.Digest.String(), stmts) + desc, err := ic.commitAttestationsManifest(ctx, opts, *desc, stmts, opts.OCIArtifact) if err != nil { return nil, err } @@ -553,7 +555,7 @@ func (ic *ImageWriter) commitDistributionManifest(ctx context.Context, opts *Ima }, &configDesc, nil } -func (ic *ImageWriter) commitAttestationsManifest(ctx context.Context, opts *ImageCommitOpts, target string, statements []intoto.Statement) (*ocispecs.Descriptor, error) { +func (ic *ImageWriter) commitAttestationsManifest(ctx context.Context, opts *ImageCommitOpts, target ocispecs.Descriptor, statements []intoto.Statement, ociArtifact bool) (*ocispecs.Descriptor, error) { var ( manifestType = ocispecs.MediaTypeImageManifest configType = ocispecs.MediaTypeImageConfig @@ -588,15 +590,21 @@ func (ic *ImageWriter) commitAttestationsManifest(ctx context.Context, opts *Ima layers[i] = desc } - config, err := attestationsConfig(layers) - if err != nil { - return nil, err - } - configDigest := digest.FromBytes(config) - configDesc := ocispecs.Descriptor{ - Digest: configDigest, - Size: int64(len(config)), - MediaType: configType, + configDesc := ocispecs.DescriptorEmptyJSON + config := configDesc.Data + + if !ociArtifact { + var err error + config, err = attestationsConfig(layers) + if err != nil { + return nil, err + } + configDigest := digest.FromBytes(config) + configDesc = ocispecs.Descriptor{ + Digest: configDigest, + Size: int64(len(config)), + MediaType: configType, + } } mfst := ocispecs.Manifest{ @@ -604,15 +612,16 @@ func (ic *ImageWriter) commitAttestationsManifest(ctx context.Context, opts *Ima Versioned: specs.Versioned{ SchemaVersion: 2, }, - Config: ocispecs.Descriptor{ - Digest: configDigest, - Size: int64(len(config)), - MediaType: configType, - }, + Config: configDesc, + } + + if ociArtifact { + mfst.ArtifactType = attestationManifestArtifactType + mfst.Subject = &target } labels := map[string]string{ - "containerd.io/gc.ref.content.0": configDigest.String(), + "containerd.io/gc.ref.content.0": configDesc.Digest.String(), } for i, desc := range layers { desc.Annotations = RemoveInternalLayerAnnotations(desc.Annotations, opts.OCITypes) @@ -635,7 +644,7 @@ func (ic *ImageWriter) commitAttestationsManifest(ctx context.Context, opts *Ima if err := content.WriteBlob(ctx, ic.opt.ContentStore, mfstDigest.String(), bytes.NewReader(mfstJSON), mfstDesc, content.WithLabels((labels))); err != nil { return nil, done(errors.Wrapf(err, "error writing manifest blob %s", mfstDigest)) } - if err := content.WriteBlob(ctx, ic.opt.ContentStore, configDigest.String(), bytes.NewReader(config), configDesc); err != nil { + if err := content.WriteBlob(ctx, ic.opt.ContentStore, configDesc.Digest.String(), bytes.NewReader(config), configDesc); err != nil { return nil, done(errors.Wrap(err, "error writing config blob")) } done(nil) @@ -646,7 +655,7 @@ func (ic *ImageWriter) commitAttestationsManifest(ctx context.Context, opts *Ima MediaType: manifestType, Annotations: map[string]string{ attestationTypes.DockerAnnotationReferenceType: attestationTypes.DockerAnnotationReferenceTypeDefault, - attestationTypes.DockerAnnotationReferenceDigest: target, + attestationTypes.DockerAnnotationReferenceDigest: string(target.Digest), }, }, nil } diff --git a/vendor/github.com/moby/buildkit/exporter/oci/export.go b/vendor/github.com/moby/buildkit/exporter/oci/export.go index df8e4134ea..69eabfebb2 100644 --- a/vendor/github.com/moby/buildkit/exporter/oci/export.go +++ b/vendor/github.com/moby/buildkit/exporter/oci/export.go @@ -10,8 +10,8 @@ import ( "strings" "time" - archiveexporter "github.com/containerd/containerd/images/archive" - "github.com/containerd/containerd/leases" + archiveexporter "github.com/containerd/containerd/v2/core/images/archive" + "github.com/containerd/containerd/v2/core/leases" "github.com/distribution/reference" "github.com/moby/buildkit/cache" cacheconfig "github.com/moby/buildkit/cache/config" diff --git a/vendor/github.com/moby/buildkit/exporter/verifier/platforms.go b/vendor/github.com/moby/buildkit/exporter/verifier/platforms.go index 5144b78e8e..3bcc573c85 100644 --- a/vendor/github.com/moby/buildkit/exporter/verifier/platforms.go +++ b/vendor/github.com/moby/buildkit/exporter/verifier/platforms.go @@ -46,13 +46,14 @@ func CheckInvalidPlatforms[T comparable](ctx context.Context, res *result.Result }) } p = platforms.Normalize(p) - _, ok := reqMap[platforms.Format(p)] + formatted := platforms.FormatAll(p) + _, ok := reqMap[formatted] if ok { warnings = append(warnings, client.VertexWarning{ Short: []byte(fmt.Sprintf("Duplicate platform result requested %q", v)), }) } - reqMap[platforms.Format(p)] = struct{}{} + reqMap[formatted] = struct{}{} reqList = append(reqList, exptypes.Platform{Platform: p}) } @@ -62,10 +63,25 @@ func CheckInvalidPlatforms[T comparable](ctx context.Context, res *result.Result if len(reqMap) == 1 && len(ps.Platforms) == 1 { pp := platforms.Normalize(ps.Platforms[0].Platform) - if _, ok := reqMap[platforms.Format(pp)]; !ok { - return []client.VertexWarning{{ - Short: []byte(fmt.Sprintf("Requested platform %q does not match result platform %q", req.Platforms[0], platforms.Format(pp))), - }}, nil + if _, ok := reqMap[platforms.FormatAll(pp)]; !ok { + // The requested platform will often not have an OSVersion on it, but the + // resulting platform may have one. + // This should not be considered a mismatch, so check again after clearing + // the OSVersion from the returned platform. + reqP, err := platforms.Parse(req.Platforms[0]) + if err != nil { + return nil, err + } + reqP = platforms.Normalize(reqP) + if reqP.OSVersion == "" && reqP.OSVersion != pp.OSVersion { + pp.OSVersion = "" + } + + if _, ok := reqMap[platforms.FormatAll(pp)]; !ok { + return []client.VertexWarning{{ + Short: []byte(fmt.Sprintf("Requested platform %q does not match result platform %q", req.Platforms[0], platforms.FormatAll(pp))), + }}, nil + } } return nil, nil } @@ -81,7 +97,7 @@ func CheckInvalidPlatforms[T comparable](ctx context.Context, res *result.Result if !mismatch { for _, p := range ps.Platforms { pp := platforms.Normalize(p.Platform) - if _, ok := reqMap[platforms.Format(pp)]; !ok { + if _, ok := reqMap[platforms.FormatAll(pp)]; !ok { mismatch = true break } @@ -100,7 +116,7 @@ func CheckInvalidPlatforms[T comparable](ctx context.Context, res *result.Result func platformsString(ps []exptypes.Platform) string { var ss []string for _, p := range ps { - ss = append(ss, platforms.Format(platforms.Normalize(p.Platform))) + ss = append(ss, platforms.FormatAll(platforms.Normalize(p.Platform))) } sort.Strings(ss) return strings.Join(ss, ",") diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go index 31ca7381c7..62b76bd5e2 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/builder/build.go @@ -160,7 +160,7 @@ func Build(ctx context.Context, c client.Client) (_ *client.Result, err error) { if platform != nil { p = *platform } - scanTargets.Store(platforms.Format(platforms.Normalize(p)), scanTarget) + scanTargets.Store(platforms.FormatAll(platforms.Normalize(p)), scanTarget) return ref, img, baseImg, nil }) diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go index 934c3a338e..88e5943ebd 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go @@ -46,6 +46,7 @@ import ( digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" + mode "github.com/tonistiigi/dchapes-mode" "golang.org/x/sync/errgroup" ) @@ -519,7 +520,7 @@ func toDispatchState(ctx context.Context, dt []byte, opt ConvertOpt) (*dispatchS if reachable { prefix := "[" if opt.MultiPlatformRequested && platform != nil { - prefix += platforms.Format(*platform) + " " + prefix += platforms.FormatAll(*platform) + " " } prefix += "internal]" mutRef, dgst, dt, err := metaResolver.ResolveImageConfig(ctx, d.stage.BaseName, sourceresolver.Opt{ @@ -1390,19 +1391,26 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error { copyOpt = append(copyOpt, llb.WithExcludePatterns(cfg.excludePatterns)) } - var mode *llb.ChmodOpt + var chopt *llb.ChmodOpt if cfg.chmod != "" { - mode = &llb.ChmodOpt{} + chopt = &llb.ChmodOpt{} p, err := strconv.ParseUint(cfg.chmod, 8, 32) nonOctalErr := errors.Errorf("invalid chmod parameter: '%v'. it should be octal string and between 0 and 07777", cfg.chmod) if err == nil { if p > 0o7777 { return nonOctalErr } - mode.Mode = os.FileMode(p) + chopt.Mode = os.FileMode(p) } else { if featureCopyChmodNonOctalEnabled { - mode.ModeStr = cfg.chmod + if _, err := mode.Parse(cfg.chmod); err != nil { + var ne *strconv.NumError + if errors.As(err, &ne) { + return nonOctalErr // return nonOctalErr for compatibility if the value looks numeric + } + return err + } + chopt.ModeStr = cfg.chmod } else { return nonOctalErr } @@ -1467,7 +1475,7 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error { } st := llb.Git(gitRef.Remote, commit, gitOptions...) opts := append([]llb.CopyOption{&llb.CopyInfo{ - Mode: mode, + Mode: chopt, CreateDestPath: true, }}, copyOpt...) if a == nil { @@ -1496,7 +1504,7 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error { st := llb.HTTP(src, llb.Filename(f), llb.WithCustomName(pgName), llb.Checksum(cfg.checksum), dfCmd(cfg.params)) opts := append([]llb.CopyOption{&llb.CopyInfo{ - Mode: mode, + Mode: chopt, CreateDestPath: true, }}, copyOpt...) @@ -1532,7 +1540,7 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error { } opts := append([]llb.CopyOption{&llb.CopyInfo{ - Mode: mode, + Mode: chopt, FollowSymlinks: true, CopyDirContentsOnly: true, IncludePatterns: patterns, @@ -1565,7 +1573,7 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error { ) opts := append([]llb.CopyOption{&llb.CopyInfo{ - Mode: mode, + Mode: chopt, CreateDestPath: true, }}, copyOpt...) @@ -2102,7 +2110,7 @@ func prefixCommand(ds *dispatchState, str string, prefixPlatform bool, platform } out := "[" if prefixPlatform && platform != nil { - out += platforms.Format(*platform) + formatTargetPlatform(*platform, platformFromEnv(env)) + " " + out += platforms.FormatAll(*platform) + formatTargetPlatform(*platform, platformFromEnv(env)) + " " } if ds.stageName != "" { out += ds.stageName + " " @@ -2136,7 +2144,7 @@ func formatTargetPlatform(base ocispecs.Platform, target *ocispecs.Platform) str return "->" + archVariant } if p.OS != base.OS { - return "->" + platforms.Format(p) + return "->" + platforms.FormatAll(p) } return "" } @@ -2483,8 +2491,8 @@ func wrapSuggestAny(err error, keys map[string]struct{}, options []string) error func validateBaseImagePlatform(name string, expected, actual ocispecs.Platform, location []parser.Range, lint *linter.Linter) { if expected.OS != actual.OS || expected.Architecture != actual.Architecture { - expectedStr := platforms.Format(platforms.Normalize(expected)) - actualStr := platforms.Format(platforms.Normalize(actual)) + expectedStr := platforms.FormatAll(platforms.Normalize(expected)) + actualStr := platforms.FormatAll(platforms.Normalize(actual)) msg := linter.RuleInvalidBaseImagePlatform.Format(name, expectedStr, actualStr) lint.Run(&linter.RuleInvalidBaseImagePlatform, location, msg) } diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/platform.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/platform.go index 5eb99d919a..3a983fb86c 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/platform.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/platform.go @@ -45,10 +45,12 @@ func defaultArgs(po *platformOpt, overrides map[string]string, target string) *l s := [...][2]string{ {"BUILDPLATFORM", platforms.Format(bp)}, {"BUILDOS", bp.OS}, + {"BUILDOSVERSION", bp.OSVersion}, {"BUILDARCH", bp.Architecture}, {"BUILDVARIANT", bp.Variant}, - {"TARGETPLATFORM", platforms.Format(tp)}, + {"TARGETPLATFORM", platforms.FormatAll(tp)}, {"TARGETOS", tp.OS}, + {"TARGETOSVERSION", tp.OSVersion}, {"TARGETARCH", tp.Architecture}, {"TARGETVARIANT", tp.Variant}, {"TARGETSTAGE", target}, diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/directives.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/directives.go index 651b13148c..4f1e1300ec 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/directives.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/directives.go @@ -112,10 +112,15 @@ func (d *DirectiveParser) ParseAll(data []byte) ([]*Directive, error) { // This allows for a flexible range of input formats, and appropriate syntax // selection. func DetectSyntax(dt []byte) (string, string, []Range, bool) { - return ParseDirective(keySyntax, dt) + return parseDirective(keySyntax, dt, true) } func ParseDirective(key string, dt []byte) (string, string, []Range, bool) { + return parseDirective(key, dt, false) +} + +func parseDirective(key string, dt []byte, anyFormat bool) (string, string, []Range, bool) { + dt = discardBOM(dt) dt, hadShebang, err := discardShebang(dt) if err != nil { return "", "", nil, false @@ -131,6 +136,10 @@ func ParseDirective(key string, dt []byte) (string, string, []Range, bool) { return syntax, cmdline, loc, true } + if !anyFormat { + return "", "", nil, false + } + // use directive with different comment prefix, and search for //key= directiveParser = DirectiveParser{line: line} directiveParser.setComment("//") @@ -171,3 +180,7 @@ func discardShebang(dt []byte) ([]byte, bool, error) { } return dt, false, nil } + +func discardBOM(dt []byte) []byte { + return bytes.TrimPrefix(dt, []byte{0xEF, 0xBB, 0xBF}) +} diff --git a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go index 740f03b708..1b0a962286 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerfile/parser/parser.go @@ -291,7 +291,7 @@ func Parse(rwc io.Reader) (*Result, error) { bytesRead := scanner.Bytes() if currentLine == 0 { // First line, strip the byte-order-marker if present - bytesRead = bytes.TrimPrefix(bytesRead, utf8bom) + bytesRead = discardBOM(bytesRead) } if isComment(bytesRead) { comment := strings.TrimSpace(string(bytesRead[1:])) @@ -522,8 +522,6 @@ func isEmptyContinuationLine(line []byte) bool { return len(trimLeadingWhitespace(trimNewline(line))) == 0 } -var utf8bom = []byte{0xEF, 0xBB, 0xBF} - func trimContinuationCharacter(line []byte, d *directives) ([]byte, bool) { if d.lineContinuationRegex.Match(line) { line = d.lineContinuationRegex.ReplaceAll(line, []byte("$1")) diff --git a/vendor/github.com/moby/buildkit/frontend/dockerui/build.go b/vendor/github.com/moby/buildkit/frontend/dockerui/build.go index 3be8e86432..cc93dfaf36 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerui/build.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerui/build.go @@ -70,7 +70,7 @@ func (bc *Client) Build(ctx context.Context, fn BuildFunc) (*ResultBuilder, erro } p = platforms.Normalize(p) - k := platforms.Format(p) + k := platforms.FormatAll(p) if bc.MultiPlatformRequested { res.AddRef(k, ref) diff --git a/vendor/github.com/moby/buildkit/frontend/dockerui/config.go b/vendor/github.com/moby/buildkit/frontend/dockerui/config.go index 5d4868435a..a880c886ee 100644 --- a/vendor/github.com/moby/buildkit/frontend/dockerui/config.go +++ b/vendor/github.com/moby/buildkit/frontend/dockerui/config.go @@ -463,7 +463,7 @@ func (bc *Client) NamedContext(ctx context.Context, name string, opt ContextOpt) if opt.Platform != nil { pp = *opt.Platform } - pname := name + "::" + platforms.Format(platforms.Normalize(pp)) + pname := name + "::" + platforms.FormatAll(platforms.Normalize(pp)) st, img, err := bc.namedContext(ctx, name, pname, opt) if err != nil || st != nil { return st, img, err diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go index 103b649f5b..324455f976 100644 --- a/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go +++ b/vendor/github.com/moby/buildkit/frontend/gateway/gateway.go @@ -15,8 +15,8 @@ import ( "syscall" "time" - "github.com/containerd/containerd/defaults" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/defaults" "github.com/distribution/reference" "github.com/docker/docker/pkg/idtools" apitypes "github.com/moby/buildkit/api/types" diff --git a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go index bdcc12c6b1..0890439108 100644 --- a/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go +++ b/vendor/github.com/moby/buildkit/frontend/gateway/pb/gateway.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/frontend/gateway/pb/gateway.proto diff --git a/vendor/github.com/moby/buildkit/session/auth/auth.pb.go b/vendor/github.com/moby/buildkit/session/auth/auth.pb.go index 39295b176a..30913d3e85 100644 --- a/vendor/github.com/moby/buildkit/session/auth/auth.pb.go +++ b/vendor/github.com/moby/buildkit/session/auth/auth.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/session/auth/auth.proto diff --git a/vendor/github.com/moby/buildkit/session/content/attachable.go b/vendor/github.com/moby/buildkit/session/content/attachable.go index 5c0801ac92..a1197d6dda 100644 --- a/vendor/github.com/moby/buildkit/session/content/attachable.go +++ b/vendor/github.com/moby/buildkit/session/content/attachable.go @@ -4,8 +4,8 @@ import ( "context" api "github.com/containerd/containerd/api/services/content/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/services/content/contentserver" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/plugins/services/content/contentserver" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/session" digest "github.com/opencontainers/go-digest" diff --git a/vendor/github.com/moby/buildkit/session/content/caller.go b/vendor/github.com/moby/buildkit/session/content/caller.go index b712bf9174..513e4d6d28 100644 --- a/vendor/github.com/moby/buildkit/session/content/caller.go +++ b/vendor/github.com/moby/buildkit/session/content/caller.go @@ -4,8 +4,8 @@ import ( "context" api "github.com/containerd/containerd/api/services/content/v1" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/content/proxy" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/content/proxy" "github.com/moby/buildkit/session" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/session/filesync/filesync.pb.go b/vendor/github.com/moby/buildkit/session/filesync/filesync.pb.go index 01c3b6e393..2a51550b77 100644 --- a/vendor/github.com/moby/buildkit/session/filesync/filesync.pb.go +++ b/vendor/github.com/moby/buildkit/session/filesync/filesync.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/session/filesync/filesync.proto diff --git a/vendor/github.com/moby/buildkit/session/grpc.go b/vendor/github.com/moby/buildkit/session/grpc.go index f6834e826c..c207e5ddea 100644 --- a/vendor/github.com/moby/buildkit/session/grpc.go +++ b/vendor/github.com/moby/buildkit/session/grpc.go @@ -7,7 +7,7 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd/defaults" + "github.com/containerd/containerd/v2/defaults" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/grpcerrors" "github.com/moby/buildkit/util/tracing" diff --git a/vendor/github.com/moby/buildkit/session/secrets/secrets.pb.go b/vendor/github.com/moby/buildkit/session/secrets/secrets.pb.go index f9d2ea984e..aa89213b73 100644 --- a/vendor/github.com/moby/buildkit/session/secrets/secrets.pb.go +++ b/vendor/github.com/moby/buildkit/session/secrets/secrets.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/session/secrets/secrets.proto diff --git a/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go b/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go index 7a76dfca0b..330645a670 100644 --- a/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go +++ b/vendor/github.com/moby/buildkit/session/sshforward/ssh.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/session/sshforward/ssh.proto diff --git a/vendor/github.com/moby/buildkit/session/upload/upload.pb.go b/vendor/github.com/moby/buildkit/session/upload/upload.pb.go index 64bdfc86c0..3a9d8bb77c 100644 --- a/vendor/github.com/moby/buildkit/session/upload/upload.pb.go +++ b/vendor/github.com/moby/buildkit/session/upload/upload.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/session/upload/upload.proto diff --git a/vendor/github.com/moby/buildkit/snapshot/containerd/content.go b/vendor/github.com/moby/buildkit/snapshot/containerd/content.go index e418a06712..c50cc99ace 100644 --- a/vendor/github.com/moby/buildkit/snapshot/containerd/content.go +++ b/vendor/github.com/moby/buildkit/snapshot/containerd/content.go @@ -3,8 +3,8 @@ package containerd import ( "context" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/namespaces" cerrdefs "github.com/containerd/errdefs" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/snapshot/containerd/snapshotter.go b/vendor/github.com/moby/buildkit/snapshot/containerd/snapshotter.go index 93e8b395b6..12ff1b1dad 100644 --- a/vendor/github.com/moby/buildkit/snapshot/containerd/snapshotter.go +++ b/vendor/github.com/moby/buildkit/snapshot/containerd/snapshotter.go @@ -3,9 +3,9 @@ package containerd import ( "context" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/namespaces" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/snapshot" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/snapshot/diffapply_linux.go b/vendor/github.com/moby/buildkit/snapshot/diffapply_linux.go index fa67d09487..f9250a27bb 100644 --- a/vendor/github.com/moby/buildkit/snapshot/diffapply_linux.go +++ b/vendor/github.com/moby/buildkit/snapshot/diffapply_linux.go @@ -8,10 +8,10 @@ import ( "strings" "syscall" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" - "github.com/containerd/containerd/snapshots/overlay/overlayutils" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" + "github.com/containerd/containerd/v2/plugins/snapshots/overlay/overlayutils" "github.com/containerd/continuity/fs" "github.com/containerd/continuity/sysx" "github.com/hashicorp/go-multierror" diff --git a/vendor/github.com/moby/buildkit/snapshot/diffapply_unsupported.go b/vendor/github.com/moby/buildkit/snapshot/diffapply_unsupported.go index ed27048bef..ddbd61a5c3 100644 --- a/vendor/github.com/moby/buildkit/snapshot/diffapply_unsupported.go +++ b/vendor/github.com/moby/buildkit/snapshot/diffapply_unsupported.go @@ -6,8 +6,8 @@ import ( "context" "runtime" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/pkg/errors" ) diff --git a/vendor/github.com/moby/buildkit/snapshot/imagerefchecker/checker.go b/vendor/github.com/moby/buildkit/snapshot/imagerefchecker/checker.go index eb6cb25f32..6a596a5e6b 100644 --- a/vendor/github.com/moby/buildkit/snapshot/imagerefchecker/checker.go +++ b/vendor/github.com/moby/buildkit/snapshot/imagerefchecker/checker.go @@ -6,8 +6,8 @@ import ( "strings" "sync" - "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/moby/buildkit/cache" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter.go b/vendor/github.com/moby/buildkit/snapshot/localmounter.go index 304eebc9e0..3df452de8a 100644 --- a/vendor/github.com/moby/buildkit/snapshot/localmounter.go +++ b/vendor/github.com/moby/buildkit/snapshot/localmounter.go @@ -3,7 +3,7 @@ package snapshot import ( "sync" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" ) type Mounter interface { diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter_darwin.go b/vendor/github.com/moby/buildkit/snapshot/localmounter_darwin.go index 1b20e931d7..7f7c89a769 100644 --- a/vendor/github.com/moby/buildkit/snapshot/localmounter_darwin.go +++ b/vendor/github.com/moby/buildkit/snapshot/localmounter_darwin.go @@ -3,7 +3,7 @@ package snapshot import ( "os" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/pkg/errors" "golang.org/x/sys/unix" ) diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter_freebsd.go b/vendor/github.com/moby/buildkit/snapshot/localmounter_freebsd.go index 4c9f1774ea..b6200437d0 100644 --- a/vendor/github.com/moby/buildkit/snapshot/localmounter_freebsd.go +++ b/vendor/github.com/moby/buildkit/snapshot/localmounter_freebsd.go @@ -3,7 +3,7 @@ package snapshot import ( "os" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/pkg/errors" ) diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter_linux.go b/vendor/github.com/moby/buildkit/snapshot/localmounter_linux.go index cc98cac719..09094a9a23 100644 --- a/vendor/github.com/moby/buildkit/snapshot/localmounter_linux.go +++ b/vendor/github.com/moby/buildkit/snapshot/localmounter_linux.go @@ -5,7 +5,7 @@ import ( "path/filepath" "syscall" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" rootlessmountopts "github.com/moby/buildkit/util/rootless/mountopts" "github.com/moby/sys/userns" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go b/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go index 348641e4ff..783545f225 100644 --- a/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go +++ b/vendor/github.com/moby/buildkit/snapshot/localmounter_windows.go @@ -4,7 +4,7 @@ import ( "os" "github.com/Microsoft/go-winio/pkg/bindfilter" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" cerrdefs "github.com/containerd/errdefs" "github.com/pkg/errors" "golang.org/x/sys/windows" diff --git a/vendor/github.com/moby/buildkit/snapshot/merge.go b/vendor/github.com/moby/buildkit/snapshot/merge.go index c37205569c..7c1e320c07 100644 --- a/vendor/github.com/moby/buildkit/snapshot/merge.go +++ b/vendor/github.com/moby/buildkit/snapshot/merge.go @@ -4,8 +4,8 @@ import ( "context" "strconv" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/leaseutil" diff --git a/vendor/github.com/moby/buildkit/snapshot/snapshotter.go b/vendor/github.com/moby/buildkit/snapshot/snapshotter.go index e512b345b0..fde9957fce 100644 --- a/vendor/github.com/moby/buildkit/snapshot/snapshotter.go +++ b/vendor/github.com/moby/buildkit/snapshot/snapshotter.go @@ -6,8 +6,8 @@ import ( "strings" "sync" - "github.com/containerd/containerd/mount" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/core/snapshots" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/executor" "github.com/moby/sys/userns" diff --git a/vendor/github.com/moby/buildkit/snapshot/staticmountable.go b/vendor/github.com/moby/buildkit/snapshot/staticmountable.go index 62533ba318..098146824a 100644 --- a/vendor/github.com/moby/buildkit/snapshot/staticmountable.go +++ b/vendor/github.com/moby/buildkit/snapshot/staticmountable.go @@ -4,7 +4,7 @@ import ( "os" "sync/atomic" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/docker/docker/pkg/idtools" ) diff --git a/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go b/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go index 6dfaa81fb6..e940433956 100644 --- a/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go +++ b/vendor/github.com/moby/buildkit/solver/errdefs/errdefs.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/solver/errdefs/errdefs.proto diff --git a/vendor/github.com/moby/buildkit/solver/jobs.go b/vendor/github.com/moby/buildkit/solver/jobs.go index d8cce3abdc..68b4e53c96 100644 --- a/vendor/github.com/moby/buildkit/solver/jobs.go +++ b/vendor/github.com/moby/buildkit/solver/jobs.go @@ -734,10 +734,12 @@ func (j *Job) walkProvenance(ctx context.Context, e Edge, f func(ProvenanceProvi visited[e.Vertex.Digest()] = struct{}{} if st, ok := j.list.actives[e.Vertex.Digest()]; ok { st.mu.Lock() - if wp, ok := st.op.op.(ProvenanceProvider); ok { - if err := f(wp); err != nil { - st.mu.Unlock() - return err + if st.op != nil && st.op.op != nil { + if wp, ok := st.op.op.(ProvenanceProvider); ok { + if err := f(wp); err != nil { + st.mu.Unlock() + return err + } } } st.mu.Unlock() diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go index bf682ec6ce..18b20ba0c7 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/bridge.go @@ -354,9 +354,9 @@ func (b *llbBridge) ResolveSourceMetadata(ctx context.Context, op *pb.SourceOp, } id := op.Identifier if opt.Platform != nil { - id += platforms.Format(*opt.Platform) + id += platforms.FormatAll(*opt.Platform) } else { - id += platforms.Format(platforms.DefaultSpec()) + id += platforms.FormatAll(platforms.DefaultSpec()) } pol, err := loadSourcePolicy(b.builder) if err != nil { diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go b/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go index 1d4abb36aa..465cfe67ae 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/file/backend.go @@ -67,6 +67,40 @@ func mkdir(d string, action *pb.FileActionMkDir, user *copy.User, idmap *idtools return nil } +func symlink(d string, action *pb.FileActionSymlink, user *copy.User, idmap *idtools.IdentityMapping) (err error) { + defer func() { + var osErr *os.PathError + if errors.As(err, &osErr) { + // remove system root from error path if present + osErr.Path = strings.TrimPrefix(osErr.Path, d) + } + }() + + newpath, err := fs.RootPath(d, filepath.Join("/", action.Newpath)) + if err != nil { + return errors.WithStack(err) + } + + ch, err := mapUserToChowner(user, idmap) + if err != nil { + return err + } + + if err := os.Symlink(action.Oldpath, newpath); err != nil { + return errors.WithStack(err) + } + + if err := copy.Chown(newpath, nil, ch); err != nil { + return errors.WithStack(err) + } + + if err := copy.Utimes(newpath, timestampToTime(action.Timestamp)); err != nil { + return errors.WithStack(err) + } + + return nil +} + func mkfile(d string, action *pb.FileActionMkFile, user *copy.User, idmap *idtools.IdentityMapping) (err error) { defer func() { var osErr *os.PathError @@ -304,6 +338,27 @@ func (fb *Backend) Mkfile(ctx context.Context, m, user, group fileoptypes.Mount, return mkfile(dir, action, u, mnt.m.IdentityMapping()) } +func (fb *Backend) Symlink(ctx context.Context, m, user, group fileoptypes.Mount, action *pb.FileActionSymlink) error { + mnt, ok := m.(*Mount) + if !ok { + return errors.Errorf("invalid mount type %T", m) + } + + lm := snapshot.LocalMounter(mnt.m) + dir, err := lm.Mount() + if err != nil { + return err + } + defer lm.Unmount() + + u, err := fb.readUserWrapper(action.Owner, user, group) + if err != nil { + return err + } + + return symlink(dir, action, u, mnt.m.IdentityMapping()) +} + func (fb *Backend) Rm(ctx context.Context, m fileoptypes.Mount, action *pb.FileActionRm) error { mnt, ok := m.(*Mount) if !ok { diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/history.go b/vendor/github.com/moby/buildkit/solver/llbsolver/history.go index e0b19f7512..04e83cfbdd 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/history.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/history.go @@ -13,8 +13,8 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/leases" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/leases" cerrdefs "github.com/containerd/errdefs" controlapi "github.com/moby/buildkit/api/services/control" "github.com/moby/buildkit/client" diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go b/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go index c95fe4966b..92b103458f 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/mounts/mount.go @@ -11,7 +11,7 @@ import ( "github.com/moby/buildkit/util/bklog" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/client" diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go index b10ce03e21..e34bedabba 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/exec_binfmt.go @@ -7,7 +7,7 @@ import ( "path/filepath" "strings" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/containerd/platforms" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/snapshot" diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go index d93fbdb0bb..13c6beda85 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/file.go @@ -84,6 +84,13 @@ func (f *fileOp) CacheMap(ctx context.Context, g session.Group, index int) (*sol if err != nil { return nil, false, err } + case *pb.FileAction_Symlink: + p := a.Symlink.CloneVT() + markInvalid(action.Input) + dt, err = json.Marshal(p) + if err != nil { + return nil, false, err + } case *pb.FileAction_Rm: p := a.Rm.CloneVT() markInvalid(action.Input) @@ -586,6 +593,14 @@ func (s *FileOpSolver) getInput(ctx context.Context, idx int, inputs []fileoptyp if err := s.b.Mkdir(ctx, inpMount, user, group, a.Mkdir); err != nil { return input{}, err } + case *pb.FileAction_Symlink: + user, group, err := loadOwner(ctx, a.Symlink.Owner) + if err != nil { + return input{}, err + } + if err := s.b.Symlink(ctx, inpMount, user, group, a.Symlink); err != nil { + return input{}, err + } case *pb.FileAction_Mkfile: user, group, err := loadOwner(ctx, a.Mkfile.Owner) if err != nil { diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go index bc35a07d97..db892b805d 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/ops/fileoptypes/types.go @@ -19,6 +19,7 @@ type Mount interface { type Backend interface { Mkdir(context.Context, Mount, Mount, Mount, *pb.FileActionMkDir) error + Symlink(context.Context, Mount, Mount, Mount, *pb.FileActionSymlink) error Mkfile(context.Context, Mount, Mount, Mount, *pb.FileActionMkFile) error Rm(context.Context, Mount, *pb.FileActionRm) error Copy(context.Context, Mount, Mount, Mount, Mount, *pb.FileActionCopy) error diff --git a/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go b/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go index c5e3870a9d..21ae0f9f22 100644 --- a/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go +++ b/vendor/github.com/moby/buildkit/solver/llbsolver/vertex.go @@ -381,6 +381,8 @@ func fileOpName(actions []*pb.FileAction) string { names = append(names, fmt.Sprintf("mkdir %s", a.Mkdir.Path)) case *pb.FileAction_Mkfile: names = append(names, fmt.Sprintf("mkfile %s", a.Mkfile.Path)) + case *pb.FileAction_Symlink: + names = append(names, fmt.Sprintf("symlink %s -> %s", a.Symlink.Newpath, a.Symlink.Oldpath)) case *pb.FileAction_Rm: names = append(names, fmt.Sprintf("rm %s", a.Rm.Path)) case *pb.FileAction_Copy: diff --git a/vendor/github.com/moby/buildkit/solver/pb/caps.go b/vendor/github.com/moby/buildkit/solver/pb/caps.go index 57bbce05ab..8ba462978b 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/caps.go +++ b/vendor/github.com/moby/buildkit/solver/pb/caps.go @@ -68,6 +68,7 @@ const ( CapFileRmNoFollowSymlink apicaps.CapID = "file.rm.nofollowsymlink" CapFileCopyAlwaysReplaceExistingDestPaths apicaps.CapID = "file.copy.alwaysreplaceexistingdestpaths" CapFileCopyModeStringFormat apicaps.CapID = "file.copy.modestring" + CapFileSymlinkCreate apicaps.CapID = "file.symlink.create" CapConstraints apicaps.CapID = "constraints" CapPlatform apicaps.CapID = "platform" @@ -402,6 +403,12 @@ func init() { Status: apicaps.CapStatusExperimental, }) + Caps.Init(apicaps.Cap{ + ID: CapFileSymlinkCreate, + Enabled: true, + Status: apicaps.CapStatusExperimental, + }) + Caps.Init(apicaps.Cap{ ID: CapConstraints, Enabled: true, diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go b/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go index 09237031ee..6975da4cee 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go +++ b/vendor/github.com/moby/buildkit/solver/pb/ops.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/solver/pb/ops.proto @@ -2303,6 +2303,7 @@ type FileAction struct { // *FileAction_Mkfile // *FileAction_Mkdir // *FileAction_Rm + // *FileAction_Symlink Action isFileAction_Action `protobuf_oneof:"action"` } @@ -2392,6 +2393,13 @@ func (x *FileAction) GetRm() *FileActionRm { return nil } +func (x *FileAction) GetSymlink() *FileActionSymlink { + if x, ok := x.GetAction().(*FileAction_Symlink); ok { + return x.Symlink + } + return nil +} + type isFileAction_Action interface { isFileAction_Action() } @@ -2416,6 +2424,11 @@ type FileAction_Rm struct { Rm *FileActionRm `protobuf:"bytes,7,opt,name=rm,proto3,oneof"` } +type FileAction_Symlink struct { + // FileActionSymlink creates a symlink + Symlink *FileActionSymlink `protobuf:"bytes,8,opt,name=symlink,proto3,oneof"` +} + func (*FileAction_Copy) isFileAction_Action() {} func (*FileAction_Mkfile) isFileAction_Action() {} @@ -2424,6 +2437,8 @@ func (*FileAction_Mkdir) isFileAction_Action() {} func (*FileAction_Rm) isFileAction_Action() {} +func (*FileAction_Symlink) isFileAction_Action() {} + type FileActionCopy struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2678,6 +2693,79 @@ func (x *FileActionMkFile) GetTimestamp() int64 { return 0 } +type FileActionSymlink struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + // destination path for the new file representing the link + Oldpath string `protobuf:"bytes,1,opt,name=oldpath,proto3" json:"oldpath,omitempty"` + // source path for the link + Newpath string `protobuf:"bytes,2,opt,name=newpath,proto3" json:"newpath,omitempty"` + // optional owner for the new file + Owner *ChownOpt `protobuf:"bytes,3,opt,name=owner,proto3" json:"owner,omitempty"` + // optional created time override + Timestamp int64 `protobuf:"varint,4,opt,name=timestamp,proto3" json:"timestamp,omitempty"` +} + +func (x *FileActionSymlink) Reset() { + *x = FileActionSymlink{} + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) +} + +func (x *FileActionSymlink) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*FileActionSymlink) ProtoMessage() {} + +func (x *FileActionSymlink) ProtoReflect() protoreflect.Message { + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] + if x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use FileActionSymlink.ProtoReflect.Descriptor instead. +func (*FileActionSymlink) Descriptor() ([]byte, []int) { + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{32} +} + +func (x *FileActionSymlink) GetOldpath() string { + if x != nil { + return x.Oldpath + } + return "" +} + +func (x *FileActionSymlink) GetNewpath() string { + if x != nil { + return x.Newpath + } + return "" +} + +func (x *FileActionSymlink) GetOwner() *ChownOpt { + if x != nil { + return x.Owner + } + return nil +} + +func (x *FileActionSymlink) GetTimestamp() int64 { + if x != nil { + return x.Timestamp + } + return 0 +} + type FileActionMkDir struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2697,7 +2785,7 @@ type FileActionMkDir struct { func (x *FileActionMkDir) Reset() { *x = FileActionMkDir{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2709,7 +2797,7 @@ func (x *FileActionMkDir) String() string { func (*FileActionMkDir) ProtoMessage() {} func (x *FileActionMkDir) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[32] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2722,7 +2810,7 @@ func (x *FileActionMkDir) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionMkDir.ProtoReflect.Descriptor instead. func (*FileActionMkDir) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{32} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{33} } func (x *FileActionMkDir) GetPath() string { @@ -2775,7 +2863,7 @@ type FileActionRm struct { func (x *FileActionRm) Reset() { *x = FileActionRm{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2787,7 +2875,7 @@ func (x *FileActionRm) String() string { func (*FileActionRm) ProtoMessage() {} func (x *FileActionRm) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[33] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2800,7 +2888,7 @@ func (x *FileActionRm) ProtoReflect() protoreflect.Message { // Deprecated: Use FileActionRm.ProtoReflect.Descriptor instead. func (*FileActionRm) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{33} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{34} } func (x *FileActionRm) GetPath() string { @@ -2835,7 +2923,7 @@ type ChownOpt struct { func (x *ChownOpt) Reset() { *x = ChownOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2847,7 +2935,7 @@ func (x *ChownOpt) String() string { func (*ChownOpt) ProtoMessage() {} func (x *ChownOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[34] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2860,7 +2948,7 @@ func (x *ChownOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use ChownOpt.ProtoReflect.Descriptor instead. func (*ChownOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{34} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{35} } func (x *ChownOpt) GetUser() *UserOpt { @@ -2893,7 +2981,7 @@ type UserOpt struct { func (x *UserOpt) Reset() { *x = UserOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2905,7 +2993,7 @@ func (x *UserOpt) String() string { func (*UserOpt) ProtoMessage() {} func (x *UserOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2918,7 +3006,7 @@ func (x *UserOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use UserOpt.ProtoReflect.Descriptor instead. func (*UserOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{35} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{36} } func (m *UserOpt) GetUser() isUserOpt_User { @@ -2969,7 +3057,7 @@ type NamedUserOpt struct { func (x *NamedUserOpt) Reset() { *x = NamedUserOpt{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2981,7 +3069,7 @@ func (x *NamedUserOpt) String() string { func (*NamedUserOpt) ProtoMessage() {} func (x *NamedUserOpt) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2994,7 +3082,7 @@ func (x *NamedUserOpt) ProtoReflect() protoreflect.Message { // Deprecated: Use NamedUserOpt.ProtoReflect.Descriptor instead. func (*NamedUserOpt) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{36} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{37} } func (x *NamedUserOpt) GetName() string { @@ -3021,7 +3109,7 @@ type MergeInput struct { func (x *MergeInput) Reset() { *x = MergeInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3033,7 +3121,7 @@ func (x *MergeInput) String() string { func (*MergeInput) ProtoMessage() {} func (x *MergeInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[37] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3046,7 +3134,7 @@ func (x *MergeInput) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeInput.ProtoReflect.Descriptor instead. func (*MergeInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{37} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{38} } func (x *MergeInput) GetInput() int64 { @@ -3066,7 +3154,7 @@ type MergeOp struct { func (x *MergeOp) Reset() { *x = MergeOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3078,7 +3166,7 @@ func (x *MergeOp) String() string { func (*MergeOp) ProtoMessage() {} func (x *MergeOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[38] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3091,7 +3179,7 @@ func (x *MergeOp) ProtoReflect() protoreflect.Message { // Deprecated: Use MergeOp.ProtoReflect.Descriptor instead. func (*MergeOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{38} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{39} } func (x *MergeOp) GetInputs() []*MergeInput { @@ -3111,7 +3199,7 @@ type LowerDiffInput struct { func (x *LowerDiffInput) Reset() { *x = LowerDiffInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3123,7 +3211,7 @@ func (x *LowerDiffInput) String() string { func (*LowerDiffInput) ProtoMessage() {} func (x *LowerDiffInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[39] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3136,7 +3224,7 @@ func (x *LowerDiffInput) ProtoReflect() protoreflect.Message { // Deprecated: Use LowerDiffInput.ProtoReflect.Descriptor instead. func (*LowerDiffInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{39} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{40} } func (x *LowerDiffInput) GetInput() int64 { @@ -3156,7 +3244,7 @@ type UpperDiffInput struct { func (x *UpperDiffInput) Reset() { *x = UpperDiffInput{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3168,7 +3256,7 @@ func (x *UpperDiffInput) String() string { func (*UpperDiffInput) ProtoMessage() {} func (x *UpperDiffInput) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[40] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3181,7 +3269,7 @@ func (x *UpperDiffInput) ProtoReflect() protoreflect.Message { // Deprecated: Use UpperDiffInput.ProtoReflect.Descriptor instead. func (*UpperDiffInput) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{40} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{41} } func (x *UpperDiffInput) GetInput() int64 { @@ -3202,7 +3290,7 @@ type DiffOp struct { func (x *DiffOp) Reset() { *x = DiffOp{} - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[42] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3214,7 +3302,7 @@ func (x *DiffOp) String() string { func (*DiffOp) ProtoMessage() {} func (x *DiffOp) ProtoReflect() protoreflect.Message { - mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[41] + mi := &file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[42] if x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3227,7 +3315,7 @@ func (x *DiffOp) ProtoReflect() protoreflect.Message { // Deprecated: Use DiffOp.ProtoReflect.Descriptor instead. func (*DiffOp) Descriptor() ([]byte, []int) { - return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{41} + return file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP(), []int{42} } func (x *DiffOp) GetLower() *LowerDiffInput { @@ -3509,7 +3597,7 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_rawDesc = []byte{ 0x76, 0x61, 0x6c, 0x75, 0x65, 0x3a, 0x02, 0x38, 0x01, 0x22, 0x32, 0x0a, 0x06, 0x46, 0x69, 0x6c, 0x65, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x97, 0x02, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xca, 0x02, 0x0a, 0x0a, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x61, 0x72, 0x79, 0x49, @@ -3526,121 +3614,133 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_rawDesc = []byte{ 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x48, 0x00, 0x52, 0x05, 0x6d, 0x6b, 0x64, 0x69, 0x72, 0x12, 0x22, 0x0a, 0x02, 0x72, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x48, 0x00, 0x52, 0x02, 0x72, 0x6d, 0x42, 0x08, 0x0a, - 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x04, 0x0a, 0x0e, 0x46, 0x69, 0x6c, 0x65, - 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x10, 0x0a, 0x03, 0x73, 0x72, - 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72, 0x63, 0x12, 0x12, 0x0a, 0x04, - 0x64, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, 0x65, 0x73, 0x74, - 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, - 0x77, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x66, 0x6f, 0x6c, 0x6c, - 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0d, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x28, - 0x0a, 0x0f, 0x64, 0x69, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x72, 0x43, 0x6f, 0x70, 0x79, - 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x20, 0x61, 0x74, 0x74, 0x65, - 0x6d, 0x70, 0x74, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, - 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x55, 0x6e, 0x70, 0x61, 0x63, - 0x6b, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, - 0x6c, 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, - 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0e, 0x63, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, 0x24, 0x0a, 0x0d, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x09, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, - 0x72, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, - 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, - 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, - 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x74, - 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, 0x6e, 0x63, 0x6c, - 0x75, 0x64, 0x65, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x65, - 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x18, - 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, - 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, - 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, - 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x08, 0x52, 0x1e, - 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, - 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x12, 0x18, - 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x10, 0x46, 0x69, 0x6c, - 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x12, 0x0a, - 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, - 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, - 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9d, 0x01, 0x0a, 0x0f, - 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x12, - 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, - 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, - 0x6b, 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, - 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, - 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, - 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x6e, 0x0a, 0x0c, 0x46, - 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x70, - 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, - 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, - 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, - 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x4e, 0x0a, 0x08, 0x43, - 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, - 0x70, 0x74, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, - 0x70, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x53, 0x0a, 0x07, 0x55, - 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x61, 0x6d, 0x65, - 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06, 0x62, 0x79, 0x4e, 0x61, - 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x04, 0x62, 0x79, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, - 0x48, 0x00, 0x52, 0x04, 0x62, 0x79, 0x49, 0x44, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, - 0x22, 0x38, 0x0a, 0x0c, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0a, 0x4d, 0x65, - 0x72, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x31, - 0x0a, 0x07, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x12, 0x26, 0x0a, 0x06, 0x69, 0x6e, 0x70, - 0x75, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, - 0x65, 0x72, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, - 0x73, 0x22, 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, - 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x26, 0x0a, 0x0e, 0x55, 0x70, 0x70, - 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, - 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, - 0x74, 0x22, 0x5c, 0x0a, 0x06, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x05, 0x6c, - 0x6f, 0x77, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, - 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, - 0x6c, 0x6f, 0x77, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, - 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2a, - 0x28, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, - 0x53, 0x45, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, - 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x29, 0x0a, 0x0c, 0x53, 0x65, 0x63, - 0x75, 0x72, 0x69, 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x41, 0x4e, - 0x44, 0x42, 0x4f, 0x58, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x53, 0x45, 0x43, 0x55, - 0x52, 0x45, 0x10, 0x01, 0x2a, 0x40, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x08, 0x0a, 0x04, 0x42, 0x49, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, - 0x45, 0x43, 0x52, 0x45, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x02, - 0x12, 0x09, 0x0a, 0x05, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, - 0x4d, 0x50, 0x46, 0x53, 0x10, 0x04, 0x2a, 0x31, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x43, - 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, - 0x45, 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4e, 0x10, 0x01, - 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x46, 0x46, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0f, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x0a, 0x0a, 0x06, - 0x53, 0x48, 0x41, 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, - 0x41, 0x54, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, - 0x02, 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, - 0x6d, 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, - 0x6c, 0x76, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x48, 0x00, 0x52, 0x02, 0x72, 0x6d, 0x12, 0x31, 0x0a, + 0x07, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x70, 0x62, 0x2e, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, + 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x48, 0x00, 0x52, 0x07, 0x73, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, + 0x42, 0x08, 0x0a, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0xde, 0x04, 0x0a, 0x0e, 0x46, + 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x70, 0x79, 0x12, 0x10, 0x0a, + 0x03, 0x73, 0x72, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x03, 0x73, 0x72, 0x63, 0x12, + 0x12, 0x0a, 0x04, 0x64, 0x65, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x64, + 0x65, 0x73, 0x74, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, + 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0d, 0x66, + 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0d, 0x66, 0x6f, 0x6c, 0x6c, 0x6f, 0x77, 0x53, 0x79, 0x6d, 0x6c, 0x69, 0x6e, + 0x6b, 0x12, 0x28, 0x0a, 0x0f, 0x64, 0x69, 0x72, 0x43, 0x6f, 0x70, 0x79, 0x43, 0x6f, 0x6e, 0x74, + 0x65, 0x6e, 0x74, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0f, 0x64, 0x69, 0x72, 0x43, + 0x6f, 0x70, 0x79, 0x43, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x4a, 0x0a, 0x20, 0x61, + 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x55, 0x6e, 0x70, 0x61, 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x6b, + 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, + 0x07, 0x20, 0x01, 0x28, 0x08, 0x52, 0x20, 0x61, 0x74, 0x74, 0x65, 0x6d, 0x70, 0x74, 0x55, 0x6e, + 0x70, 0x61, 0x63, 0x6b, 0x44, 0x6f, 0x63, 0x6b, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x70, 0x61, 0x74, + 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x26, 0x0a, 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x18, 0x08, 0x20, 0x01, 0x28, 0x08, 0x52, + 0x0e, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x12, + 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, + 0x18, 0x09, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, + 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x12, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x57, 0x69, 0x6c, + 0x64, 0x63, 0x61, 0x72, 0x64, 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, + 0x6d, 0x70, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x12, 0x29, 0x0a, 0x10, 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, + 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x69, + 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x29, + 0x0a, 0x10, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x5f, 0x70, 0x61, 0x74, 0x74, 0x65, 0x72, + 0x6e, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x65, 0x78, 0x63, 0x6c, 0x75, 0x64, + 0x65, 0x50, 0x61, 0x74, 0x74, 0x65, 0x72, 0x6e, 0x73, 0x12, 0x46, 0x0a, 0x1e, 0x61, 0x6c, 0x77, + 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, + 0x08, 0x52, 0x1e, 0x61, 0x6c, 0x77, 0x61, 0x79, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x61, 0x63, 0x65, + 0x45, 0x78, 0x69, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x44, 0x65, 0x73, 0x74, 0x50, 0x61, 0x74, 0x68, + 0x73, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x18, 0x0f, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x6f, 0x64, 0x65, 0x53, 0x74, 0x72, 0x22, 0x90, 0x01, 0x0a, 0x10, + 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x46, 0x69, 0x6c, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x70, 0x61, 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x64, 0x61, 0x74, 0x61, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x64, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x05, + 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, + 0x2e, 0x43, 0x68, 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, + 0x12, 0x1c, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x89, + 0x01, 0x0a, 0x11, 0x46, 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x79, 0x6d, + 0x6c, 0x69, 0x6e, 0x6b, 0x12, 0x18, 0x0a, 0x07, 0x6f, 0x6c, 0x64, 0x70, 0x61, 0x74, 0x68, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6f, 0x6c, 0x64, 0x70, 0x61, 0x74, 0x68, 0x12, 0x18, + 0x0a, 0x07, 0x6e, 0x65, 0x77, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x07, 0x6e, 0x65, 0x77, 0x70, 0x61, 0x74, 0x68, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, + 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x9d, 0x01, 0x0a, 0x0f, 0x46, + 0x69, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4d, 0x6b, 0x44, 0x69, 0x72, 0x12, 0x12, + 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x12, 0x12, 0x0a, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, + 0x52, 0x04, 0x6d, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x6d, 0x61, 0x6b, 0x65, 0x50, 0x61, + 0x72, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6d, 0x61, 0x6b, + 0x65, 0x50, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x22, 0x0a, 0x05, 0x6f, 0x77, 0x6e, 0x65, + 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0c, 0x2e, 0x70, 0x62, 0x2e, 0x43, 0x68, 0x6f, + 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x52, 0x05, 0x6f, 0x77, 0x6e, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, + 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x22, 0x6e, 0x0a, 0x0c, 0x46, 0x69, + 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x6d, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, + 0x74, 0x68, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x12, 0x24, + 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, 0x6f, 0x75, 0x6e, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x4e, 0x6f, 0x74, 0x46, + 0x6f, 0x75, 0x6e, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x57, 0x69, 0x6c, + 0x64, 0x63, 0x61, 0x72, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0d, 0x61, 0x6c, 0x6c, + 0x6f, 0x77, 0x57, 0x69, 0x6c, 0x64, 0x63, 0x61, 0x72, 0x64, 0x22, 0x4e, 0x0a, 0x08, 0x43, 0x68, + 0x6f, 0x77, 0x6e, 0x4f, 0x70, 0x74, 0x12, 0x1f, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, + 0x74, 0x52, 0x04, 0x75, 0x73, 0x65, 0x72, 0x12, 0x21, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x0b, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x4f, 0x70, 0x74, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x22, 0x53, 0x0a, 0x07, 0x55, 0x73, + 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, 0x2a, 0x0a, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x70, 0x62, 0x2e, 0x4e, 0x61, 0x6d, 0x65, 0x64, + 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x48, 0x00, 0x52, 0x06, 0x62, 0x79, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x14, 0x0a, 0x04, 0x62, 0x79, 0x49, 0x44, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x48, + 0x00, 0x52, 0x04, 0x62, 0x79, 0x49, 0x44, 0x42, 0x06, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x72, 0x22, + 0x38, 0x0a, 0x0c, 0x4e, 0x61, 0x6d, 0x65, 0x64, 0x55, 0x73, 0x65, 0x72, 0x4f, 0x70, 0x74, 0x12, + 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, + 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x22, 0x0a, 0x0a, 0x4d, 0x65, 0x72, + 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x31, 0x0a, + 0x07, 0x4d, 0x65, 0x72, 0x67, 0x65, 0x4f, 0x70, 0x12, 0x26, 0x0a, 0x06, 0x69, 0x6e, 0x70, 0x75, + 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x0e, 0x2e, 0x70, 0x62, 0x2e, 0x4d, 0x65, + 0x72, 0x67, 0x65, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x06, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x73, + 0x22, 0x26, 0x0a, 0x0e, 0x4c, 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, 0x22, 0x26, 0x0a, 0x0e, 0x55, 0x70, 0x70, 0x65, + 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x69, 0x6e, + 0x70, 0x75, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x69, 0x6e, 0x70, 0x75, 0x74, + 0x22, 0x5c, 0x0a, 0x06, 0x44, 0x69, 0x66, 0x66, 0x4f, 0x70, 0x12, 0x28, 0x0a, 0x05, 0x6c, 0x6f, + 0x77, 0x65, 0x72, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x4c, + 0x6f, 0x77, 0x65, 0x72, 0x44, 0x69, 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x6c, + 0x6f, 0x77, 0x65, 0x72, 0x12, 0x28, 0x0a, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x70, 0x62, 0x2e, 0x55, 0x70, 0x70, 0x65, 0x72, 0x44, 0x69, + 0x66, 0x66, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x05, 0x75, 0x70, 0x70, 0x65, 0x72, 0x2a, 0x28, + 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x09, 0x0a, 0x05, 0x55, 0x4e, 0x53, + 0x45, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, 0x04, 0x48, 0x4f, 0x53, 0x54, 0x10, 0x01, 0x12, 0x08, + 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x2a, 0x29, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x75, + 0x72, 0x69, 0x74, 0x79, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x41, 0x4e, 0x44, + 0x42, 0x4f, 0x58, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x49, 0x4e, 0x53, 0x45, 0x43, 0x55, 0x52, + 0x45, 0x10, 0x01, 0x2a, 0x40, 0x0a, 0x09, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x08, 0x0a, 0x04, 0x42, 0x49, 0x4e, 0x44, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x53, 0x45, + 0x43, 0x52, 0x45, 0x54, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x53, 0x53, 0x48, 0x10, 0x02, 0x12, + 0x09, 0x0a, 0x05, 0x43, 0x41, 0x43, 0x48, 0x45, 0x10, 0x03, 0x12, 0x09, 0x0a, 0x05, 0x54, 0x4d, + 0x50, 0x46, 0x53, 0x10, 0x04, 0x2a, 0x31, 0x0a, 0x11, 0x4d, 0x6f, 0x75, 0x6e, 0x74, 0x43, 0x6f, + 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x43, 0x61, 0x63, 0x68, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x44, 0x45, + 0x46, 0x41, 0x55, 0x4c, 0x54, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4f, 0x4e, 0x10, 0x01, 0x12, + 0x07, 0x0a, 0x03, 0x4f, 0x46, 0x46, 0x10, 0x02, 0x2a, 0x36, 0x0a, 0x0f, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x53, 0x68, 0x61, 0x72, 0x69, 0x6e, 0x67, 0x4f, 0x70, 0x74, 0x12, 0x0a, 0x0a, 0x06, 0x53, + 0x48, 0x41, 0x52, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x50, 0x52, 0x49, 0x56, 0x41, + 0x54, 0x45, 0x10, 0x01, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x02, + 0x42, 0x24, 0x5a, 0x22, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6d, + 0x6f, 0x62, 0x79, 0x2f, 0x62, 0x75, 0x69, 0x6c, 0x64, 0x6b, 0x69, 0x74, 0x2f, 0x73, 0x6f, 0x6c, + 0x76, 0x65, 0x72, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3656,7 +3756,7 @@ func file_github_com_moby_buildkit_solver_pb_ops_proto_rawDescGZIP() []byte { } var file_github_com_moby_buildkit_solver_pb_ops_proto_enumTypes = make([]protoimpl.EnumInfo, 5) -var file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes = make([]protoimpl.MessageInfo, 49) +var file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes = make([]protoimpl.MessageInfo, 50) var file_github_com_moby_buildkit_solver_pb_ops_proto_goTypes = []any{ (NetMode)(0), // 0: pb.NetMode (SecurityMode)(0), // 1: pb.SecurityMode @@ -3695,23 +3795,24 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_goTypes = []any{ (*FileAction)(nil), // 34: pb.FileAction (*FileActionCopy)(nil), // 35: pb.FileActionCopy (*FileActionMkFile)(nil), // 36: pb.FileActionMkFile - (*FileActionMkDir)(nil), // 37: pb.FileActionMkDir - (*FileActionRm)(nil), // 38: pb.FileActionRm - (*ChownOpt)(nil), // 39: pb.ChownOpt - (*UserOpt)(nil), // 40: pb.UserOpt - (*NamedUserOpt)(nil), // 41: pb.NamedUserOpt - (*MergeInput)(nil), // 42: pb.MergeInput - (*MergeOp)(nil), // 43: pb.MergeOp - (*LowerDiffInput)(nil), // 44: pb.LowerDiffInput - (*UpperDiffInput)(nil), // 45: pb.UpperDiffInput - (*DiffOp)(nil), // 46: pb.DiffOp - nil, // 47: pb.SourceOp.AttrsEntry - nil, // 48: pb.BuildOp.InputsEntry - nil, // 49: pb.BuildOp.AttrsEntry - nil, // 50: pb.OpMetadata.DescriptionEntry - nil, // 51: pb.OpMetadata.CapsEntry - nil, // 52: pb.Source.LocationsEntry - nil, // 53: pb.Definition.MetadataEntry + (*FileActionSymlink)(nil), // 37: pb.FileActionSymlink + (*FileActionMkDir)(nil), // 38: pb.FileActionMkDir + (*FileActionRm)(nil), // 39: pb.FileActionRm + (*ChownOpt)(nil), // 40: pb.ChownOpt + (*UserOpt)(nil), // 41: pb.UserOpt + (*NamedUserOpt)(nil), // 42: pb.NamedUserOpt + (*MergeInput)(nil), // 43: pb.MergeInput + (*MergeOp)(nil), // 44: pb.MergeOp + (*LowerDiffInput)(nil), // 45: pb.LowerDiffInput + (*UpperDiffInput)(nil), // 46: pb.UpperDiffInput + (*DiffOp)(nil), // 47: pb.DiffOp + nil, // 48: pb.SourceOp.AttrsEntry + nil, // 49: pb.BuildOp.InputsEntry + nil, // 50: pb.BuildOp.AttrsEntry + nil, // 51: pb.OpMetadata.DescriptionEntry + nil, // 52: pb.OpMetadata.CapsEntry + nil, // 53: pb.Source.LocationsEntry + nil, // 54: pb.Definition.MetadataEntry } var file_github_com_moby_buildkit_solver_pb_ops_proto_depIdxs = []int32{ 7, // 0: pb.Op.inputs:type_name -> pb.Input @@ -3719,8 +3820,8 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_depIdxs = []int32{ 18, // 2: pb.Op.source:type_name -> pb.SourceOp 33, // 3: pb.Op.file:type_name -> pb.FileOp 19, // 4: pb.Op.build:type_name -> pb.BuildOp - 43, // 5: pb.Op.merge:type_name -> pb.MergeOp - 46, // 6: pb.Op.diff:type_name -> pb.DiffOp + 44, // 5: pb.Op.merge:type_name -> pb.MergeOp + 47, // 6: pb.Op.diff:type_name -> pb.DiffOp 6, // 7: pb.Op.platform:type_name -> pb.Platform 31, // 8: pb.Op.constraints:type_name -> pb.WorkerConstraints 9, // 9: pb.ExecOp.meta:type_name -> pb.Meta @@ -3738,45 +3839,47 @@ var file_github_com_moby_buildkit_solver_pb_ops_proto_depIdxs = []int32{ 17, // 21: pb.Mount.SSHOpt:type_name -> pb.SSHOpt 3, // 22: pb.Mount.contentCache:type_name -> pb.MountContentCache 4, // 23: pb.CacheOpt.sharing:type_name -> pb.CacheSharingOpt - 47, // 24: pb.SourceOp.attrs:type_name -> pb.SourceOp.AttrsEntry - 48, // 25: pb.BuildOp.inputs:type_name -> pb.BuildOp.InputsEntry + 48, // 24: pb.SourceOp.attrs:type_name -> pb.SourceOp.AttrsEntry + 49, // 25: pb.BuildOp.inputs:type_name -> pb.BuildOp.InputsEntry 32, // 26: pb.BuildOp.def:type_name -> pb.Definition - 49, // 27: pb.BuildOp.attrs:type_name -> pb.BuildOp.AttrsEntry - 50, // 28: pb.OpMetadata.description:type_name -> pb.OpMetadata.DescriptionEntry + 50, // 27: pb.BuildOp.attrs:type_name -> pb.BuildOp.AttrsEntry + 51, // 28: pb.OpMetadata.description:type_name -> pb.OpMetadata.DescriptionEntry 28, // 29: pb.OpMetadata.export_cache:type_name -> pb.ExportCache - 51, // 30: pb.OpMetadata.caps:type_name -> pb.OpMetadata.CapsEntry + 52, // 30: pb.OpMetadata.caps:type_name -> pb.OpMetadata.CapsEntry 29, // 31: pb.OpMetadata.progress_group:type_name -> pb.ProgressGroup - 52, // 32: pb.Source.locations:type_name -> pb.Source.LocationsEntry + 53, // 32: pb.Source.locations:type_name -> pb.Source.LocationsEntry 24, // 33: pb.Source.infos:type_name -> pb.SourceInfo 25, // 34: pb.Locations.locations:type_name -> pb.Location 32, // 35: pb.SourceInfo.definition:type_name -> pb.Definition 26, // 36: pb.Location.ranges:type_name -> pb.Range 27, // 37: pb.Range.start:type_name -> pb.Position 27, // 38: pb.Range.end:type_name -> pb.Position - 53, // 39: pb.Definition.metadata:type_name -> pb.Definition.MetadataEntry + 54, // 39: pb.Definition.metadata:type_name -> pb.Definition.MetadataEntry 22, // 40: pb.Definition.Source:type_name -> pb.Source 34, // 41: pb.FileOp.actions:type_name -> pb.FileAction 35, // 42: pb.FileAction.copy:type_name -> pb.FileActionCopy 36, // 43: pb.FileAction.mkfile:type_name -> pb.FileActionMkFile - 37, // 44: pb.FileAction.mkdir:type_name -> pb.FileActionMkDir - 38, // 45: pb.FileAction.rm:type_name -> pb.FileActionRm - 39, // 46: pb.FileActionCopy.owner:type_name -> pb.ChownOpt - 39, // 47: pb.FileActionMkFile.owner:type_name -> pb.ChownOpt - 39, // 48: pb.FileActionMkDir.owner:type_name -> pb.ChownOpt - 40, // 49: pb.ChownOpt.user:type_name -> pb.UserOpt - 40, // 50: pb.ChownOpt.group:type_name -> pb.UserOpt - 41, // 51: pb.UserOpt.byName:type_name -> pb.NamedUserOpt - 42, // 52: pb.MergeOp.inputs:type_name -> pb.MergeInput - 44, // 53: pb.DiffOp.lower:type_name -> pb.LowerDiffInput - 45, // 54: pb.DiffOp.upper:type_name -> pb.UpperDiffInput - 20, // 55: pb.BuildOp.InputsEntry.value:type_name -> pb.BuildInput - 23, // 56: pb.Source.LocationsEntry.value:type_name -> pb.Locations - 21, // 57: pb.Definition.MetadataEntry.value:type_name -> pb.OpMetadata - 58, // [58:58] is the sub-list for method output_type - 58, // [58:58] is the sub-list for method input_type - 58, // [58:58] is the sub-list for extension type_name - 58, // [58:58] is the sub-list for extension extendee - 0, // [0:58] is the sub-list for field type_name + 38, // 44: pb.FileAction.mkdir:type_name -> pb.FileActionMkDir + 39, // 45: pb.FileAction.rm:type_name -> pb.FileActionRm + 37, // 46: pb.FileAction.symlink:type_name -> pb.FileActionSymlink + 40, // 47: pb.FileActionCopy.owner:type_name -> pb.ChownOpt + 40, // 48: pb.FileActionMkFile.owner:type_name -> pb.ChownOpt + 40, // 49: pb.FileActionSymlink.owner:type_name -> pb.ChownOpt + 40, // 50: pb.FileActionMkDir.owner:type_name -> pb.ChownOpt + 41, // 51: pb.ChownOpt.user:type_name -> pb.UserOpt + 41, // 52: pb.ChownOpt.group:type_name -> pb.UserOpt + 42, // 53: pb.UserOpt.byName:type_name -> pb.NamedUserOpt + 43, // 54: pb.MergeOp.inputs:type_name -> pb.MergeInput + 45, // 55: pb.DiffOp.lower:type_name -> pb.LowerDiffInput + 46, // 56: pb.DiffOp.upper:type_name -> pb.UpperDiffInput + 20, // 57: pb.BuildOp.InputsEntry.value:type_name -> pb.BuildInput + 23, // 58: pb.Source.LocationsEntry.value:type_name -> pb.Locations + 21, // 59: pb.Definition.MetadataEntry.value:type_name -> pb.OpMetadata + 60, // [60:60] is the sub-list for method output_type + 60, // [60:60] is the sub-list for method input_type + 60, // [60:60] is the sub-list for extension type_name + 60, // [60:60] is the sub-list for extension extendee + 0, // [0:60] is the sub-list for field type_name } func init() { file_github_com_moby_buildkit_solver_pb_ops_proto_init() } @@ -3797,8 +3900,9 @@ func file_github_com_moby_buildkit_solver_pb_ops_proto_init() { (*FileAction_Mkfile)(nil), (*FileAction_Mkdir)(nil), (*FileAction_Rm)(nil), + (*FileAction_Symlink)(nil), } - file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[35].OneofWrappers = []any{ + file_github_com_moby_buildkit_solver_pb_ops_proto_msgTypes[36].OneofWrappers = []any{ (*UserOpt_ByName)(nil), (*UserOpt_ByID)(nil), } @@ -3808,7 +3912,7 @@ func file_github_com_moby_buildkit_solver_pb_ops_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_github_com_moby_buildkit_solver_pb_ops_proto_rawDesc, NumEnums: 5, - NumMessages: 49, + NumMessages: 50, NumExtensions: 0, NumServices: 0, }, diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops.proto b/vendor/github.com/moby/buildkit/solver/pb/ops.proto index f1432af65b..5ff388299c 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/ops.proto +++ b/vendor/github.com/moby/buildkit/solver/pb/ops.proto @@ -309,6 +309,8 @@ message FileAction { FileActionMkDir mkdir = 6; // FileActionRm removes a file FileActionRm rm = 7; + // FileActionSymlink creates a symlink + FileActionSymlink symlink = 8; } } @@ -358,6 +360,17 @@ message FileActionMkFile { int64 timestamp = 5; } +message FileActionSymlink { + // destination path for the new file representing the link + string oldpath = 1; + // source path for the link + string newpath = 2; + // optional owner for the new file + ChownOpt owner = 3; + // optional created time override + int64 timestamp = 4; +} + message FileActionMkDir { // path for the new directory string path = 1; diff --git a/vendor/github.com/moby/buildkit/solver/pb/ops_vtproto.pb.go b/vendor/github.com/moby/buildkit/solver/pb/ops_vtproto.pb.go index 877f6aa2c4..9d71812423 100644 --- a/vendor/github.com/moby/buildkit/solver/pb/ops_vtproto.pb.go +++ b/vendor/github.com/moby/buildkit/solver/pb/ops_vtproto.pb.go @@ -824,6 +824,15 @@ func (m *FileAction_Rm) CloneVT() isFileAction_Action { return r } +func (m *FileAction_Symlink) CloneVT() isFileAction_Action { + if m == nil { + return (*FileAction_Symlink)(nil) + } + r := new(FileAction_Symlink) + r.Symlink = m.Symlink.CloneVT() + return r +} + func (m *FileActionCopy) CloneVT() *FileActionCopy { if m == nil { return (*FileActionCopy)(nil) @@ -888,6 +897,26 @@ func (m *FileActionMkFile) CloneMessageVT() proto.Message { return m.CloneVT() } +func (m *FileActionSymlink) CloneVT() *FileActionSymlink { + if m == nil { + return (*FileActionSymlink)(nil) + } + r := new(FileActionSymlink) + r.Oldpath = m.Oldpath + r.Newpath = m.Newpath + r.Owner = m.Owner.CloneVT() + r.Timestamp = m.Timestamp + if len(m.unknownFields) > 0 { + r.unknownFields = make([]byte, len(m.unknownFields)) + copy(r.unknownFields, m.unknownFields) + } + return r +} + +func (m *FileActionSymlink) CloneMessageVT() proto.Message { + return m.CloneVT() +} + func (m *FileActionMkDir) CloneVT() *FileActionMkDir { if m == nil { return (*FileActionMkDir)(nil) @@ -2397,6 +2426,31 @@ func (this *FileAction_Rm) EqualVT(thatIface isFileAction_Action) bool { return true } +func (this *FileAction_Symlink) EqualVT(thatIface isFileAction_Action) bool { + that, ok := thatIface.(*FileAction_Symlink) + if !ok { + return false + } + if this == that { + return true + } + if this == nil && that != nil || this != nil && that == nil { + return false + } + if p, q := this.Symlink, that.Symlink; p != q { + if p == nil { + p = &FileActionSymlink{} + } + if q == nil { + q = &FileActionSymlink{} + } + if !p.EqualVT(q) { + return false + } + } + return true +} + func (this *FileActionCopy) EqualVT(that *FileActionCopy) bool { if this == that { return true @@ -2501,6 +2555,34 @@ func (this *FileActionMkFile) EqualMessageVT(thatMsg proto.Message) bool { } return this.EqualVT(that) } +func (this *FileActionSymlink) EqualVT(that *FileActionSymlink) bool { + if this == that { + return true + } else if this == nil || that == nil { + return false + } + if this.Oldpath != that.Oldpath { + return false + } + if this.Newpath != that.Newpath { + return false + } + if !this.Owner.EqualVT(that.Owner) { + return false + } + if this.Timestamp != that.Timestamp { + return false + } + return string(this.unknownFields) == string(that.unknownFields) +} + +func (this *FileActionSymlink) EqualMessageVT(thatMsg proto.Message) bool { + that, ok := thatMsg.(*FileActionSymlink) + if !ok { + return false + } + return this.EqualVT(that) +} func (this *FileActionMkDir) EqualVT(that *FileActionMkDir) bool { if this == that { return true @@ -4922,6 +5004,29 @@ func (m *FileAction_Rm) MarshalToSizedBufferVT(dAtA []byte) (int, error) { } return len(dAtA) - i, nil } +func (m *FileAction_Symlink) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *FileAction_Symlink) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + i := len(dAtA) + if m.Symlink != nil { + size, err := m.Symlink.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x42 + } else { + i = protohelpers.EncodeVarint(dAtA, i, 0) + i-- + dAtA[i] = 0x42 + } + return len(dAtA) - i, nil +} func (m *FileActionCopy) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -5151,6 +5256,68 @@ func (m *FileActionMkFile) MarshalToSizedBufferVT(dAtA []byte) (int, error) { return len(dAtA) - i, nil } +func (m *FileActionSymlink) MarshalVT() (dAtA []byte, err error) { + if m == nil { + return nil, nil + } + size := m.SizeVT() + dAtA = make([]byte, size) + n, err := m.MarshalToSizedBufferVT(dAtA[:size]) + if err != nil { + return nil, err + } + return dAtA[:n], nil +} + +func (m *FileActionSymlink) MarshalToVT(dAtA []byte) (int, error) { + size := m.SizeVT() + return m.MarshalToSizedBufferVT(dAtA[:size]) +} + +func (m *FileActionSymlink) MarshalToSizedBufferVT(dAtA []byte) (int, error) { + if m == nil { + return 0, nil + } + i := len(dAtA) + _ = i + var l int + _ = l + if m.unknownFields != nil { + i -= len(m.unknownFields) + copy(dAtA[i:], m.unknownFields) + } + if m.Timestamp != 0 { + i = protohelpers.EncodeVarint(dAtA, i, uint64(m.Timestamp)) + i-- + dAtA[i] = 0x20 + } + if m.Owner != nil { + size, err := m.Owner.MarshalToSizedBufferVT(dAtA[:i]) + if err != nil { + return 0, err + } + i -= size + i = protohelpers.EncodeVarint(dAtA, i, uint64(size)) + i-- + dAtA[i] = 0x1a + } + if len(m.Newpath) > 0 { + i -= len(m.Newpath) + copy(dAtA[i:], m.Newpath) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Newpath))) + i-- + dAtA[i] = 0x12 + } + if len(m.Oldpath) > 0 { + i -= len(m.Oldpath) + copy(dAtA[i:], m.Oldpath) + i = protohelpers.EncodeVarint(dAtA, i, uint64(len(m.Oldpath))) + i-- + dAtA[i] = 0xa + } + return len(dAtA) - i, nil +} + func (m *FileActionMkDir) MarshalVT() (dAtA []byte, err error) { if m == nil { return nil, nil @@ -6559,6 +6726,20 @@ func (m *FileAction_Rm) SizeVT() (n int) { } return n } +func (m *FileAction_Symlink) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + if m.Symlink != nil { + l = m.Symlink.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } else { + n += 3 + } + return n +} func (m *FileActionCopy) SizeVT() (n int) { if m == nil { return 0 @@ -6652,6 +6833,31 @@ func (m *FileActionMkFile) SizeVT() (n int) { return n } +func (m *FileActionSymlink) SizeVT() (n int) { + if m == nil { + return 0 + } + var l int + _ = l + l = len(m.Oldpath) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + l = len(m.Newpath) + if l > 0 { + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Owner != nil { + l = m.Owner.SizeVT() + n += 1 + l + protohelpers.SizeOfVarint(uint64(l)) + } + if m.Timestamp != 0 { + n += 1 + protohelpers.SizeOfVarint(uint64(m.Timestamp)) + } + n += len(m.unknownFields) + return n +} + func (m *FileActionMkDir) SizeVT() (n int) { if m == nil { return 0 @@ -12355,6 +12561,47 @@ func (m *FileAction) UnmarshalVT(dAtA []byte) error { m.Action = &FileAction_Rm{Rm: v} } iNdEx = postIndex + case 8: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Symlink", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if oneof, ok := m.Action.(*FileAction_Symlink); ok { + if err := oneof.Symlink.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + } else { + v := &FileActionSymlink{} + if err := v.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + m.Action = &FileAction_Symlink{Symlink: v} + } + iNdEx = postIndex default: iNdEx = preIndex skippy, err := protohelpers.Skip(dAtA[iNdEx:]) @@ -12993,6 +13240,176 @@ func (m *FileActionMkFile) UnmarshalVT(dAtA []byte) error { } return nil } +func (m *FileActionSymlink) UnmarshalVT(dAtA []byte) error { + l := len(dAtA) + iNdEx := 0 + for iNdEx < l { + preIndex := iNdEx + var wire uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + wire |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + fieldNum := int32(wire >> 3) + wireType := int(wire & 0x7) + if wireType == 4 { + return fmt.Errorf("proto: FileActionSymlink: wiretype end group for non-group") + } + if fieldNum <= 0 { + return fmt.Errorf("proto: FileActionSymlink: illegal tag %d (wire type %d)", fieldNum, wire) + } + switch fieldNum { + case 1: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Oldpath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Oldpath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 2: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Newpath", wireType) + } + var stringLen uint64 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + stringLen |= uint64(b&0x7F) << shift + if b < 0x80 { + break + } + } + intStringLen := int(stringLen) + if intStringLen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + intStringLen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + m.Newpath = string(dAtA[iNdEx:postIndex]) + iNdEx = postIndex + case 3: + if wireType != 2 { + return fmt.Errorf("proto: wrong wireType = %d for field Owner", wireType) + } + var msglen int + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + msglen |= int(b&0x7F) << shift + if b < 0x80 { + break + } + } + if msglen < 0 { + return protohelpers.ErrInvalidLength + } + postIndex := iNdEx + msglen + if postIndex < 0 { + return protohelpers.ErrInvalidLength + } + if postIndex > l { + return io.ErrUnexpectedEOF + } + if m.Owner == nil { + m.Owner = &ChownOpt{} + } + if err := m.Owner.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil { + return err + } + iNdEx = postIndex + case 4: + if wireType != 0 { + return fmt.Errorf("proto: wrong wireType = %d for field Timestamp", wireType) + } + m.Timestamp = 0 + for shift := uint(0); ; shift += 7 { + if shift >= 64 { + return protohelpers.ErrIntOverflow + } + if iNdEx >= l { + return io.ErrUnexpectedEOF + } + b := dAtA[iNdEx] + iNdEx++ + m.Timestamp |= int64(b&0x7F) << shift + if b < 0x80 { + break + } + } + default: + iNdEx = preIndex + skippy, err := protohelpers.Skip(dAtA[iNdEx:]) + if err != nil { + return err + } + if (skippy < 0) || (iNdEx+skippy) < 0 { + return protohelpers.ErrInvalidLength + } + if (iNdEx + skippy) > l { + return io.ErrUnexpectedEOF + } + m.unknownFields = append(m.unknownFields, dAtA[iNdEx:iNdEx+skippy]...) + iNdEx += skippy + } + } + + if iNdEx > l { + return io.ErrUnexpectedEOF + } + return nil +} func (m *FileActionMkDir) UnmarshalVT(dAtA []byte) error { l := len(dAtA) iNdEx := 0 diff --git a/vendor/github.com/moby/buildkit/solver/types.go b/vendor/github.com/moby/buildkit/solver/types.go index 56a53d0fd9..be3c1b09eb 100644 --- a/vendor/github.com/moby/buildkit/solver/types.go +++ b/vendor/github.com/moby/buildkit/solver/types.go @@ -4,7 +4,7 @@ import ( "context" "time" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver/pb" "github.com/moby/buildkit/util/compression" diff --git a/vendor/github.com/moby/buildkit/source/containerimage/identifier.go b/vendor/github.com/moby/buildkit/source/containerimage/identifier.go index eb38d6093b..2dbac5790d 100644 --- a/vendor/github.com/moby/buildkit/source/containerimage/identifier.go +++ b/vendor/github.com/moby/buildkit/source/containerimage/identifier.go @@ -1,7 +1,7 @@ package containerimage import ( - "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/moby/buildkit/client" "github.com/moby/buildkit/solver/llbsolver/provenance" provenancetypes "github.com/moby/buildkit/solver/llbsolver/provenance/types" diff --git a/vendor/github.com/moby/buildkit/source/containerimage/ocilayout.go b/vendor/github.com/moby/buildkit/source/containerimage/ocilayout.go index ef579da03a..0fe0b34691 100644 --- a/vendor/github.com/moby/buildkit/source/containerimage/ocilayout.go +++ b/vendor/github.com/moby/buildkit/source/containerimage/ocilayout.go @@ -5,9 +5,9 @@ import ( "io" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/reference" - "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/reference" "github.com/moby/buildkit/client/llb/sourceresolver" "github.com/moby/buildkit/session" sessioncontent "github.com/moby/buildkit/session/content" diff --git a/vendor/github.com/moby/buildkit/source/containerimage/pull.go b/vendor/github.com/moby/buildkit/source/containerimage/pull.go index 206e4ed118..9809a96f0d 100644 --- a/vendor/github.com/moby/buildkit/source/containerimage/pull.go +++ b/vendor/github.com/moby/buildkit/source/containerimage/pull.go @@ -7,12 +7,12 @@ import ( "runtime" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/snapshots" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/snapshots" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/client" diff --git a/vendor/github.com/moby/buildkit/source/containerimage/source.go b/vendor/github.com/moby/buildkit/source/containerimage/source.go index 38be016144..ceaa0f2551 100644 --- a/vendor/github.com/moby/buildkit/source/containerimage/source.go +++ b/vendor/github.com/moby/buildkit/source/containerimage/source.go @@ -4,13 +4,13 @@ import ( "context" "strconv" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "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/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/containerd/platforms" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/client" @@ -162,7 +162,7 @@ func (is *Source) ResolveImageConfig(ctx context.Context, ref string, opt source err error ) if platform := opt.Platform; platform != nil { - key += platforms.Format(*platform) + key += platforms.FormatAll(*platform) } switch is.ResolverType { diff --git a/vendor/github.com/moby/buildkit/source/git/source_unix_nolinux.go b/vendor/github.com/moby/buildkit/source/git/source_unix_nolinux.go index 3995c10f12..5c58aa9f6c 100644 --- a/vendor/github.com/moby/buildkit/source/git/source_unix_nolinux.go +++ b/vendor/github.com/moby/buildkit/source/git/source_unix_nolinux.go @@ -10,7 +10,7 @@ import ( "syscall" "time" - "github.com/docker/docker/pkg/reexec" + "github.com/moby/sys/reexec" "golang.org/x/sys/unix" ) diff --git a/vendor/github.com/moby/buildkit/sourcepolicy/pb/policy.pb.go b/vendor/github.com/moby/buildkit/sourcepolicy/pb/policy.pb.go index ece220f8f6..7f88a34725 100644 --- a/vendor/github.com/moby/buildkit/sourcepolicy/pb/policy.pb.go +++ b/vendor/github.com/moby/buildkit/sourcepolicy/pb/policy.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/sourcepolicy/pb/policy.proto diff --git a/vendor/github.com/moby/buildkit/util/apicaps/pb/caps.pb.go b/vendor/github.com/moby/buildkit/util/apicaps/pb/caps.pb.go index 615153e7af..0d2fb580df 100644 --- a/vendor/github.com/moby/buildkit/util/apicaps/pb/caps.pb.go +++ b/vendor/github.com/moby/buildkit/util/apicaps/pb/caps.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/util/apicaps/pb/caps.proto diff --git a/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go b/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go index 7e9d8008cc..8a5d2fb62e 100644 --- a/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go +++ b/vendor/github.com/moby/buildkit/util/archutil/arm_binary.go @@ -5,4 +5,4 @@ package archutil // This file is generated by running "make archutil". // Do not edit manually. -const Binaryarm = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\x8c\x8f\xbd\x8d\xc2\x40\x10\x85\xbf\x39\xff\xdc\x49\x77\xc1\xdd\x55\x00\x19\xd1\x46\x6e\xc0\x01\x44\x10\x40\x07\x6b\x61\x09\x67\x96\x3d\x48\x64\x50\x03\x15\xb8\x08\x3a\xb2\x88\x69\x01\xad\x7f\xc4\x06\x0e\x78\xd2\x68\x34\xdf\x7b\xc1\xbc\xf3\x72\xbd\x12\x11\x46\x7d\xb0\xc0\x5d\x8a\x90\x00\xb7\x1e\x46\x09\xb3\xce\x0b\x09\x78\xa5\xa5\x9b\x0b\x74\x13\x39\xf4\x0b\xdb\xbb\xee\x99\x50\xdc\xdb\x40\xd3\x4a\xd9\xb4\xc0\x23\xfd\x03\x6c\x6e\xb3\x02\xf9\x04\xbe\x04\x53\x1f\x6a\xad\xd4\x66\x18\xcd\x4f\x8a\x49\x77\x1b\x63\x55\xab\x22\x3b\x6a\x5e\xf3\xb6\xbe\x87\x0f\xe3\xa1\x8f\x02\x3f\x9e\x1f\x0e\xdb\xbd\x10\x40\x39\x72\xd7\xe5\xdf\xcb\x89\xb7\x03\x8f\x5f\x81\xf9\x44\xee\x19\x00\x00\xff\xff\xb6\x04\x27\x29\x54\x01\x00\x00" +const Binaryarm = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\x8c\x8f\x3d\x6e\xc2\x40\x10\x85\xbf\x89\x7f\x12\x29\x29\x92\x9c\x20\xe9\xa8\xb6\xf2\x05\x5c\x40\x05\x05\xdc\x60\x2d\x2c\xe1\xce\xb2\x07\x89\x0e\xce\xc0\x09\x7c\x08\x6e\x64\x51\x73\x05\xe4\x65\x2d\xb6\x70\xc1\x93\x46\xb3\xfb\xcd\x2b\xde\x3b\xce\x97\x0b\x11\x61\xd4\x1b\x33\x86\x9f\x22\x64\xc0\xe5\x01\x93\x8c\x3f\x77\x8b\x89\x78\xba\xc5\xcd\x09\xdc\x24\x9e\xad\xaf\xba\x65\x42\x29\xf0\xed\x5e\x5d\x2f\x75\xd7\x03\xb7\xfc\x07\xb0\xa5\x2d\x2a\xe4\x1d\xf8\x10\x4c\xbb\x6b\xb5\x51\x5b\x60\xb4\x3c\x28\x26\xdf\xac\x8c\x55\x6d\xaa\x62\xaf\x65\xcb\xcb\xfa\xf4\x09\x53\xdf\x47\x81\xaf\xe0\x1e\xfb\x3d\x44\x88\xa0\x1e\xf9\xd0\xe5\x37\xf0\x49\xb0\xa3\x80\x9f\x81\xff\x09\xdf\x3d\x00\x00\xff\xff\x0b\x8f\xbf\xbd\x54\x01\x00\x00" diff --git a/vendor/github.com/moby/buildkit/util/archutil/loong64_binary.go b/vendor/github.com/moby/buildkit/util/archutil/loong64_binary.go index 249a2592dd..fdc33c1c69 100644 --- a/vendor/github.com/moby/buildkit/util/archutil/loong64_binary.go +++ b/vendor/github.com/moby/buildkit/util/archutil/loong64_binary.go @@ -5,4 +5,4 @@ package archutil // This file is generated by running "make archutil". // Do not edit manually. -const Binaryloong64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x06\x08\x6f\x03\x03\x83\x02\x88\x76\x80\x8a\x5f\x80\xd2\xce\x60\x31\x0b\x06\x26\x06\x07\x06\x66\x06\x26\x06\x90\x1a\x56\x06\x14\xa0\xc0\x88\x44\xef\x81\x0a\xc2\x68\x98\x81\x81\x4f\x4b\x52\xd8\x18\x88\x07\x02\x50\x9a\x85\x41\x94\x81\xbb\xa4\x91\x99\x81\x41\x9b\x81\x41\xaf\x38\xa3\xb8\xa4\xa8\x24\x31\x89\x41\xaf\x24\xb5\xa2\x84\x81\x0a\x80\x9b\x81\x01\xec\x27\x98\xdb\x60\xe1\xb0\x01\xca\xe7\x41\x53\xcf\x88\x85\xcf\x8c\xc5\x5c\x98\xff\x05\x09\xe8\x07\x04\x00\x00\xff\xff\x5f\xc5\x9b\x9d\x90\x01\x00\x00" +const Binaryloong64 = "\x1f\x8b\x08\x00\x00\x00\x00\x00\x02\xff\xaa\x77\xf5\x71\x63\x62\x64\x64\x80\x01\x26\x06\x08\x6f\x03\x03\x83\x02\x88\x76\x80\x8a\x5f\x80\xd2\xce\x60\x31\x0b\x06\x26\x06\x07\x06\x66\x06\x26\x06\x90\x1a\x56\x06\x14\xa0\xc0\x88\x44\xef\x81\x0a\xee\x81\x4b\x43\x64\x03\x9f\x96\xa4\xb0\x31\x10\x0f\x04\xa0\x34\x0b\x83\x28\x03\x77\x49\x23\x33\x03\x83\x36\x03\x83\x5e\x71\x46\x71\x49\x51\x49\x62\x12\x83\x5e\x49\x6a\x45\x09\x03\x15\x00\x37\xd4\x85\x30\xb7\xc1\xc2\x61\x03\x94\xcf\x83\xa6\x9e\x11\x0b\x9f\x19\x8b\xb9\x30\xff\x0b\x12\xd0\x0f\x08\x00\x00\xff\xff\x72\x81\xda\x64\x90\x01\x00\x00" diff --git a/vendor/github.com/moby/buildkit/util/compression/compression.go b/vendor/github.com/moby/buildkit/util/compression/compression.go index 9569cf6fed..e60ea1503a 100644 --- a/vendor/github.com/moby/buildkit/util/compression/compression.go +++ b/vendor/github.com/moby/buildkit/util/compression/compression.go @@ -5,9 +5,9 @@ import ( "context" "io" - cdcompression "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + cdcompression "github.com/containerd/containerd/v2/pkg/archive/compression" "github.com/containerd/stargz-snapshotter/estargz" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/iohelper" diff --git a/vendor/github.com/moby/buildkit/util/compression/estargz.go b/vendor/github.com/moby/buildkit/util/compression/estargz.go index ef6f853a75..ba68896aab 100644 --- a/vendor/github.com/moby/buildkit/util/compression/estargz.go +++ b/vendor/github.com/moby/buildkit/util/compression/estargz.go @@ -9,10 +9,10 @@ import ( "strconv" "sync" - cdcompression "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + cdcompression "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/labels" "github.com/containerd/stargz-snapshotter/estargz" "github.com/moby/buildkit/util/iohelper" digest "github.com/opencontainers/go-digest" diff --git a/vendor/github.com/moby/buildkit/util/compression/gzip.go b/vendor/github.com/moby/buildkit/util/compression/gzip.go index aafded866f..b6135e782c 100644 --- a/vendor/github.com/moby/buildkit/util/compression/gzip.go +++ b/vendor/github.com/moby/buildkit/util/compression/gzip.go @@ -5,8 +5,8 @@ import ( "context" "io" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/moby/buildkit/util/compression/nydus.go b/vendor/github.com/moby/buildkit/util/compression/nydus.go index 85c6830123..b3c85d44a7 100644 --- a/vendor/github.com/moby/buildkit/util/compression/nydus.go +++ b/vendor/github.com/moby/buildkit/util/compression/nydus.go @@ -6,9 +6,9 @@ import ( "context" "io" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/pkg/labels" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/util/compression/uncompressed.go b/vendor/github.com/moby/buildkit/util/compression/uncompressed.go index a232e58d0c..1967f5bb4b 100644 --- a/vendor/github.com/moby/buildkit/util/compression/uncompressed.go +++ b/vendor/github.com/moby/buildkit/util/compression/uncompressed.go @@ -4,8 +4,8 @@ import ( "context" "io" - "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/moby/buildkit/util/iohelper" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/moby/buildkit/util/compression/zstd.go b/vendor/github.com/moby/buildkit/util/compression/zstd.go index 3ef056e5de..dda92436b9 100644 --- a/vendor/github.com/moby/buildkit/util/compression/zstd.go +++ b/vendor/github.com/moby/buildkit/util/compression/zstd.go @@ -4,8 +4,8 @@ import ( "context" "io" - "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/klauspost/compress/zstd" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/moby/buildkit/util/contentutil/buffer.go b/vendor/github.com/moby/buildkit/util/contentutil/buffer.go index 050c063bbb..da282f8204 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/buffer.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/buffer.go @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" cerrdefs "github.com/containerd/errdefs" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/util/contentutil/copy.go b/vendor/github.com/moby/buildkit/util/contentutil/copy.go index 22ef70c12f..505a081870 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/copy.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/copy.go @@ -6,8 +6,8 @@ import ( "strings" "sync" - "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/moby/buildkit/util/resolver/limited" "github.com/moby/buildkit/util/resolver/retryhandler" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go b/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go index 6414b12f7a..f7105fd9e0 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/fetcher.go @@ -4,8 +4,8 @@ import ( "context" "io" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) diff --git a/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go b/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go index bda29e690d..98c9d89f60 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/multiprovider.go @@ -4,7 +4,7 @@ import ( "context" "sync" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/session" digest "github.com/opencontainers/go-digest" diff --git a/vendor/github.com/moby/buildkit/util/contentutil/pusher.go b/vendor/github.com/moby/buildkit/util/contentutil/pusher.go index 1ec9c7d25e..423b7f2481 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/pusher.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/pusher.go @@ -6,8 +6,8 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" cerrdefs "github.com/containerd/errdefs" digest "github.com/opencontainers/go-digest" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/util/contentutil/refs.go b/vendor/github.com/moby/buildkit/util/contentutil/refs.go index eb2bfb9c75..48abcdad55 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/refs.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/refs.go @@ -5,9 +5,9 @@ import ( "net/http" "sync" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/version" "github.com/moby/locker" diff --git a/vendor/github.com/moby/buildkit/util/contentutil/source.go b/vendor/github.com/moby/buildkit/util/contentutil/source.go index b544ed0aa3..a12d60d1ae 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/source.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/source.go @@ -4,8 +4,8 @@ import ( "net/url" "strings" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/reference" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/pkg/reference" ) func HasSource(info content.Info, refspec reference.Spec) (bool, error) { diff --git a/vendor/github.com/moby/buildkit/util/contentutil/storewithprovider.go b/vendor/github.com/moby/buildkit/util/contentutil/storewithprovider.go index 0b5df244f1..665ff1f5c2 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/storewithprovider.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/storewithprovider.go @@ -3,7 +3,7 @@ package contentutil import ( "context" - "github.com/containerd/containerd/content" + "github.com/containerd/containerd/v2/core/content" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/moby/buildkit/util/contentutil/types.go b/vendor/github.com/moby/buildkit/util/contentutil/types.go index 19dfb65408..db0116c1dd 100644 --- a/vendor/github.com/moby/buildkit/util/contentutil/types.go +++ b/vendor/github.com/moby/buildkit/util/contentutil/types.go @@ -3,7 +3,7 @@ package contentutil import ( "context" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/remotes" intoto "github.com/in-toto/in-toto-golang/in_toto" ) diff --git a/vendor/github.com/moby/buildkit/util/converter/converter.go b/vendor/github.com/moby/buildkit/util/converter/converter.go index 29d9477c57..4423ecfbdd 100644 --- a/vendor/github.com/moby/buildkit/util/converter/converter.go +++ b/vendor/github.com/moby/buildkit/util/converter/converter.go @@ -10,9 +10,9 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images/converter" - "github.com/containerd/containerd/labels" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images/converter" + "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/identity" "github.com/moby/buildkit/util/bklog" diff --git a/vendor/github.com/moby/buildkit/util/disk/disk_freebsd.go b/vendor/github.com/moby/buildkit/util/disk/disk_freebsd.go new file mode 100644 index 0000000000..755a834c39 --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/disk/disk_freebsd.go @@ -0,0 +1,22 @@ +//go:build freebsd + +package disk + +import ( + "syscall" + + "github.com/pkg/errors" +) + +func GetDiskStat(root string) (DiskStat, error) { + var st syscall.Statfs_t + if err := syscall.Statfs(root, &st); err != nil { + return DiskStat{}, errors.Wrapf(err, "could not stat fs at %s", root) + } + + return DiskStat{ + Total: int64(st.Bsize) * int64(st.Blocks), + Free: int64(st.Bsize) * int64(st.Bfree), + Available: int64(st.Bsize) * int64(st.Bavail), + }, nil +} diff --git a/vendor/github.com/moby/buildkit/util/disk/disk_netbsd.go b/vendor/github.com/moby/buildkit/util/disk/disk_netbsd.go new file mode 100644 index 0000000000..ffb3370a96 --- /dev/null +++ b/vendor/github.com/moby/buildkit/util/disk/disk_netbsd.go @@ -0,0 +1,21 @@ +//go:build netbsd + +package disk + +import ( + "github.com/pkg/errors" + "golang.org/x/sys/unix" +) + +func GetDiskStat(root string) (DiskStat, error) { + var st unix.Statvfs_t + if err := unix.Statvfs(root, &st); err != nil { + return DiskStat{}, errors.Wrapf(err, "could not stat fs at %s", root) + } + + return DiskStat{ + Total: int64(st.Frsize) * int64(st.Blocks), + Free: int64(st.Frsize) * int64(st.Bfree), + Available: int64(st.Frsize) * int64(st.Bavail), + }, nil +} diff --git a/vendor/github.com/moby/buildkit/util/disk/disk_unix.go b/vendor/github.com/moby/buildkit/util/disk/disk_unix.go index 47e6cb4390..8680fb9b22 100644 --- a/vendor/github.com/moby/buildkit/util/disk/disk_unix.go +++ b/vendor/github.com/moby/buildkit/util/disk/disk_unix.go @@ -1,4 +1,4 @@ -//go:build !windows && !openbsd +//go:build !windows && !freebsd && !netbsd && !openbsd package disk diff --git a/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go b/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go index b10fc75fc8..59f574a7d9 100644 --- a/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go +++ b/vendor/github.com/moby/buildkit/util/entitlements/security/security_linux.go @@ -6,9 +6,9 @@ import ( "os" "sync" - "github.com/containerd/containerd/containers" - "github.com/containerd/containerd/oci" - "github.com/containerd/containerd/pkg/cap" + "github.com/containerd/containerd/v2/core/containers" + "github.com/containerd/containerd/v2/pkg/cap" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/moby/buildkit/util/bklog" "github.com/moby/sys/userns" specs "github.com/opencontainers/runtime-spec/specs-go" diff --git a/vendor/github.com/moby/buildkit/util/estargz/labels.go b/vendor/github.com/moby/buildkit/util/estargz/labels.go index 50f9bf53bb..b7576ca971 100644 --- a/vendor/github.com/moby/buildkit/util/estargz/labels.go +++ b/vendor/github.com/moby/buildkit/util/estargz/labels.go @@ -4,7 +4,7 @@ import ( "fmt" "strings" - ctdlabels "github.com/containerd/containerd/labels" + ctdlabels "github.com/containerd/containerd/v2/pkg/labels" "github.com/containerd/stargz-snapshotter/estargz" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/moby/buildkit/util/imageutil/config.go b/vendor/github.com/moby/buildkit/util/imageutil/config.go index 7cce9a9e79..ba1c6852e1 100644 --- a/vendor/github.com/moby/buildkit/util/imageutil/config.go +++ b/vendor/github.com/moby/buildkit/util/imageutil/config.go @@ -7,12 +7,12 @@ import ( "sync" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/containerd/platforms" intoto "github.com/in-toto/in-toto-golang/in_toto" srctypes "github.com/moby/buildkit/source/types" diff --git a/vendor/github.com/moby/buildkit/util/imageutil/schema1.go b/vendor/github.com/moby/buildkit/util/imageutil/schema1.go index e87018e4dd..72bee0c8f2 100644 --- a/vendor/github.com/moby/buildkit/util/imageutil/schema1.go +++ b/vendor/github.com/moby/buildkit/util/imageutil/schema1.go @@ -7,7 +7,7 @@ import ( "strings" "time" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/remotes" dockerspec "github.com/moby/docker-image-spec/specs-go/v1" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/util/leaseutil/manager.go b/vendor/github.com/moby/buildkit/util/leaseutil/manager.go index 43e7f0c21c..da90a68276 100644 --- a/vendor/github.com/moby/buildkit/util/leaseutil/manager.go +++ b/vendor/github.com/moby/buildkit/util/leaseutil/manager.go @@ -5,8 +5,8 @@ import ( "sync" "time" - "github.com/containerd/containerd/leases" - "github.com/containerd/containerd/namespaces" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/namespaces" "github.com/pkg/errors" ) diff --git a/vendor/github.com/moby/buildkit/util/network/cniprovider/createns_linux.go b/vendor/github.com/moby/buildkit/util/network/cniprovider/createns_linux.go index 87513047ce..078ce821f6 100644 --- a/vendor/github.com/moby/buildkit/util/network/cniprovider/createns_linux.go +++ b/vendor/github.com/moby/buildkit/util/network/cniprovider/createns_linux.go @@ -9,7 +9,7 @@ import ( "runtime" "syscall" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/pkg/oci" "github.com/moby/buildkit/util/bklog" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/util/network/host.go b/vendor/github.com/moby/buildkit/util/network/host.go index e57e1ca21c..0bf74d7e6c 100644 --- a/vendor/github.com/moby/buildkit/util/network/host.go +++ b/vendor/github.com/moby/buildkit/util/network/host.go @@ -5,7 +5,7 @@ package network import ( "context" - "github.com/containerd/containerd/oci" + "github.com/containerd/containerd/v2/pkg/oci" resourcestypes "github.com/moby/buildkit/executor/resources/types" specs "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/vendor/github.com/moby/buildkit/util/overlay/overlay.go b/vendor/github.com/moby/buildkit/util/overlay/overlay.go index b472034c74..f889c4c34e 100644 --- a/vendor/github.com/moby/buildkit/util/overlay/overlay.go +++ b/vendor/github.com/moby/buildkit/util/overlay/overlay.go @@ -1,6 +1,6 @@ package overlay -import "github.com/containerd/containerd/mount" +import "github.com/containerd/containerd/v2/core/mount" // IsOverlayMountType returns true if the mount type is overlay-based func IsOverlayMountType(mnt mount.Mount) bool { diff --git a/vendor/github.com/moby/buildkit/util/overlay/overlay_linux.go b/vendor/github.com/moby/buildkit/util/overlay/overlay_linux.go index 1785c74c17..a6e3464b31 100644 --- a/vendor/github.com/moby/buildkit/util/overlay/overlay_linux.go +++ b/vendor/github.com/moby/buildkit/util/overlay/overlay_linux.go @@ -12,10 +12,9 @@ import ( "strings" "sync" "syscall" - "time" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/archive" "github.com/containerd/continuity/devices" "github.com/containerd/continuity/fs" "github.com/containerd/continuity/sysx" @@ -126,8 +125,7 @@ func WriteUpperdir(ctx context.Context, w io.Writer, upperdir string, lower []mo } return mount.WithTempMount(ctx, lower, func(lowerRoot string) error { return mount.WithTempMount(ctx, upperView, func(upperViewRoot string) error { - // WithWhiteoutTime(0) will no longer need to be specified when https://github.com/containerd/containerd/pull/8764 gets merged - cw := archive.NewChangeWriter(&cancellableWriter{ctx, w}, upperViewRoot, archive.WithWhiteoutTime(time.Unix(0, 0).UTC())) + cw := archive.NewChangeWriter(&cancellableWriter{ctx, w}, upperViewRoot) if err := Changes(ctx, cw.HandleChange, upperdir, upperViewRoot, lowerRoot); err != nil { if err2 := cw.Close(); err2 != nil { return errors.Wrapf(err, "failed to record upperdir changes (close error: %v)", err2) diff --git a/vendor/github.com/moby/buildkit/util/pull/pull.go b/vendor/github.com/moby/buildkit/util/pull/pull.go index c4cfedc1ba..b3982a3400 100644 --- a/vendor/github.com/moby/buildkit/util/pull/pull.go +++ b/vendor/github.com/moby/buildkit/util/pull/pull.go @@ -4,13 +4,13 @@ import ( "context" "sync" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/reference" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/remotes/docker/schema1" //nolint:staticcheck // SA1019 deprecated + "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/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker/schema1" //nolint:staticcheck // SA1019 deprecated + "github.com/containerd/containerd/v2/pkg/labels" + "github.com/containerd/containerd/v2/pkg/reference" "github.com/containerd/platforms" "github.com/moby/buildkit/session" "github.com/moby/buildkit/util/contentutil" @@ -137,10 +137,13 @@ func (p *Puller) PullManifests(ctx context.Context, getResolver SessionResolver) if p.desc.MediaType == images.MediaTypeDockerSchema1Manifest { // schema1 images are not lazy at this time, the converter will pull the whole image // including layer blobs - schema1Converter = schema1.NewConverter(p.ContentStore, &pullprogress.FetcherWithProgress{ + schema1Converter, err = schema1.NewConverter(p.ContentStore, &pullprogress.FetcherWithProgress{ Fetcher: fetcher, Manager: p.ContentStore, }) + if err != nil { + return nil, err + } handlers = append(handlers, schema1Converter) } else { // Get all the children for a descriptor diff --git a/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go b/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go index a5e359ac7e..df56b985ac 100644 --- a/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go +++ b/vendor/github.com/moby/buildkit/util/pull/pullprogress/progress.go @@ -5,8 +5,8 @@ import ( "io" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/remotes" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/util/bklog" "github.com/moby/buildkit/util/progress" diff --git a/vendor/github.com/moby/buildkit/util/push/push.go b/vendor/github.com/moby/buildkit/util/push/push.go index 7b64eb119a..5c6ec95e01 100644 --- a/vendor/github.com/moby/buildkit/util/push/push.go +++ b/vendor/github.com/moby/buildkit/util/push/push.go @@ -7,10 +7,10 @@ import ( "strings" "sync" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "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/remotes/docker" cerrdefs "github.com/containerd/errdefs" "github.com/containerd/log" "github.com/distribution/reference" diff --git a/vendor/github.com/moby/buildkit/util/resolver/authorizer.go b/vendor/github.com/moby/buildkit/util/resolver/authorizer.go index 4df357c9ee..98531a73c6 100644 --- a/vendor/github.com/moby/buildkit/util/resolver/authorizer.go +++ b/vendor/github.com/moby/buildkit/util/resolver/authorizer.go @@ -11,9 +11,9 @@ import ( "sync" "time" - "github.com/containerd/containerd/remotes/docker" - "github.com/containerd/containerd/remotes/docker/auth" - remoteserrors "github.com/containerd/containerd/remotes/errors" + "github.com/containerd/containerd/v2/core/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker/auth" + remoteserrors "github.com/containerd/containerd/v2/core/remotes/errors" cerrdefs "github.com/containerd/errdefs" "github.com/moby/buildkit/session" sessionauth "github.com/moby/buildkit/session/auth" @@ -70,17 +70,17 @@ func (a *authHandlerNS) get(ctx context.Context, host string, sm *session.Manage } if parts[0] == host { if h.authority != nil { - session, ok, err := sessionauth.VerifyTokenAuthority(ctx, host, h.authority, sm, g) + sessionID, ok, err := sessionauth.VerifyTokenAuthority(ctx, host, h.authority, sm, g) if err == nil && ok { - a.handlers[host+"/"+session] = h + a.handlers[host+"/"+sessionID] = h h.lastUsed = time.Now() return h } } else { - session, username, password, err := sessionauth.CredentialsFunc(sm, g)(host) + sessionID, username, password, err := sessionauth.CredentialsFunc(sm, g)(host) if err == nil { if username == h.common.Username && password == h.common.Secret { - a.handlers[host+"/"+session] = h + a.handlers[host+"/"+sessionID] = h h.lastUsed = time.Now() return h } @@ -130,12 +130,12 @@ func (a *dockerAuthorizer) Authorize(ctx context.Context, req *http.Request) err return nil } - auth, err := ah.authorize(ctx, a.sm, a.session) + authHeader, err := ah.authorize(ctx, a.sm, a.session) if err != nil { return err } - req.Header.Set("Authorization", auth) + req.Header.Set("Authorization", authHeader) return nil } @@ -163,7 +163,7 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R } handler = nil - // this hacky way seems to be best method to detect that error is fatal and should not be retried with a new token + // this hacky way seems to be the best method to detect that error is fatal and should not be retried with a new token if c.Parameters["error"] == "insufficient_scope" && parseScopes(oldScopes).contains(parseScopes(strings.Split(c.Parameters["scope"], " "))) { return err } @@ -180,12 +180,12 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R } var username, secret string - session, pubKey, err := sessionauth.GetTokenAuthority(ctx, host, a.sm, a.session) + sessionID, pubKey, err := sessionauth.GetTokenAuthority(ctx, host, a.sm, a.session) if err != nil { return err } if pubKey == nil { - session, username, secret, err = a.getCredentials(host) + sessionID, username, secret, err = a.getCredentials(host) if err != nil { return err } @@ -197,23 +197,20 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R } common.Scopes = parseScopes(append(common.Scopes, oldScopes...)).normalize() - a.handlers.set(host, session, newAuthHandler(host, a.client, c.Scheme, pubKey, common)) + a.handlers.set(host, sessionID, newAuthHandler(host, a.client, c.Scheme, pubKey, common)) return nil } else if c.Scheme == auth.BasicAuth { - session, username, secret, err := a.getCredentials(host) + sessionID, username, secret, err := a.getCredentials(host) if err != nil { return err } if username != "" && secret != "" { - common := auth.TokenOptions{ + a.handlers.set(host, sessionID, newAuthHandler(host, a.client, c.Scheme, nil, auth.TokenOptions{ Username: username, Secret: secret, - } - - a.handlers.set(host, session, newAuthHandler(host, a.client, c.Scheme, nil, common)) - + })) return nil } } @@ -281,8 +278,8 @@ func (ah *authHandler) doBasicAuth() (string, error) { return "", errors.New("failed to handle basic auth because missing username or secret") } - auth := base64.StdEncoding.EncodeToString([]byte(username + ":" + secret)) - return fmt.Sprintf("Basic %s", auth), nil + authHeader := base64.StdEncoding.EncodeToString([]byte(username + ":" + secret)) + return fmt.Sprintf("Basic %s", authHeader), nil } func (ah *authHandler) doBearerAuth(ctx context.Context, sm *session.Manager, g session.Group) (token string, err error) { @@ -385,10 +382,10 @@ func (ah *authHandler) fetchToken(ctx context.Context, sm *session.Manager, g se if err != nil { return nil, err } - if resp.ExpiresIn == 0 { - resp.ExpiresIn = defaultExpiration + if resp.ExpiresInSeconds == 0 { + resp.ExpiresInSeconds = defaultExpiration } - issuedAt, expires = resp.IssuedAt, resp.ExpiresIn + issuedAt, expires = resp.IssuedAt, resp.ExpiresInSeconds token = resp.AccessToken return nil, nil } @@ -399,10 +396,10 @@ func (ah *authHandler) fetchToken(ctx context.Context, sm *session.Manager, g se } return nil, err } - if resp.ExpiresIn == 0 { - resp.ExpiresIn = defaultExpiration + if resp.ExpiresInSeconds == 0 { + resp.ExpiresInSeconds = defaultExpiration } - issuedAt, expires = resp.IssuedAt, resp.ExpiresIn + issuedAt, expires = resp.IssuedAt, resp.ExpiresInSeconds token = resp.Token return nil, nil } @@ -411,10 +408,10 @@ func (ah *authHandler) fetchToken(ctx context.Context, sm *session.Manager, g se if err != nil { return nil, errors.Wrap(err, "failed to fetch anonymous token") } - if resp.ExpiresIn == 0 { - resp.ExpiresIn = defaultExpiration + if resp.ExpiresInSeconds == 0 { + resp.ExpiresInSeconds = defaultExpiration } - issuedAt, expires = resp.IssuedAt, resp.ExpiresIn + issuedAt, expires = resp.IssuedAt, resp.ExpiresInSeconds token = resp.Token return nil, nil diff --git a/vendor/github.com/moby/buildkit/util/resolver/limited/group.go b/vendor/github.com/moby/buildkit/util/resolver/limited/group.go index 2ab325ec56..25d9059160 100644 --- a/vendor/github.com/moby/buildkit/util/resolver/limited/group.go +++ b/vendor/github.com/moby/buildkit/util/resolver/limited/group.go @@ -7,9 +7,9 @@ import ( "strings" "sync" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" "github.com/distribution/reference" "github.com/moby/buildkit/util/bklog" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/util/resolver/pool.go b/vendor/github.com/moby/buildkit/util/resolver/pool.go index 60bd8b04ea..d57ced9331 100644 --- a/vendor/github.com/moby/buildkit/util/resolver/pool.go +++ b/vendor/github.com/moby/buildkit/util/resolver/pool.go @@ -9,9 +9,9 @@ import ( "sync/atomic" "time" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/images" + "github.com/containerd/containerd/v2/core/remotes" + "github.com/containerd/containerd/v2/core/remotes/docker" distreference "github.com/distribution/reference" "github.com/moby/buildkit/session" "github.com/moby/buildkit/solver/pb" diff --git a/vendor/github.com/moby/buildkit/util/resolver/resolver.go b/vendor/github.com/moby/buildkit/util/resolver/resolver.go index 77250bf0b8..8308299c10 100644 --- a/vendor/github.com/moby/buildkit/util/resolver/resolver.go +++ b/vendor/github.com/moby/buildkit/util/resolver/resolver.go @@ -14,7 +14,7 @@ import ( "syscall" "time" - "github.com/containerd/containerd/remotes/docker" + "github.com/containerd/containerd/v2/core/remotes/docker" "github.com/pkg/errors" "github.com/moby/buildkit/util/resolver/config" @@ -172,12 +172,11 @@ func NewRegistryConfig(m map[string]config.RegistryConfig) docker.RegistryHosts func newMirrorRegistryHost(mirror string) docker.RegistryHost { mirrorHost, mirrorPath := extractMirrorHostAndPath(mirror) - path := path.Join(defaultPath, mirrorPath) h := docker.RegistryHost{ Scheme: "https", Client: newDefaultClient(), Host: mirrorHost, - Path: path, + Path: path.Join(defaultPath, mirrorPath), Capabilities: docker.HostCapabilityPull | docker.HostCapabilityResolve, } diff --git a/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go b/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go index 04ce7cfd62..69f39a30a1 100644 --- a/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go +++ b/vendor/github.com/moby/buildkit/util/resolver/retryhandler/retry.go @@ -8,8 +8,8 @@ import ( "syscall" "time" - "github.com/containerd/containerd/images" - remoteserrors "github.com/containerd/containerd/remotes/errors" + "github.com/containerd/containerd/v2/core/images" + remoteserrors "github.com/containerd/containerd/v2/core/remotes/errors" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" ) diff --git a/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_linux.go b/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_linux.go index 92c542b19f..4a4a6a2233 100644 --- a/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_linux.go +++ b/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_linux.go @@ -1,7 +1,7 @@ package mountopts import ( - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/moby/buildkit/util/strutil" specs "github.com/opencontainers/runtime-spec/specs-go" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_others.go b/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_others.go index bd13b8f279..0ca8b8dee6 100644 --- a/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_others.go +++ b/vendor/github.com/moby/buildkit/util/rootless/mountopts/mountopts_others.go @@ -3,7 +3,7 @@ package mountopts import ( - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" specs "github.com/opencontainers/runtime-spec/specs-go" ) diff --git a/vendor/github.com/moby/buildkit/util/stack/stack.pb.go b/vendor/github.com/moby/buildkit/util/stack/stack.pb.go index 87917a2029..452dbd15f0 100644 --- a/vendor/github.com/moby/buildkit/util/stack/stack.pb.go +++ b/vendor/github.com/moby/buildkit/util/stack/stack.pb.go @@ -1,6 +1,6 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 +// protoc-gen-go v1.35.2 // protoc v3.11.4 // source: github.com/moby/buildkit/util/stack/stack.proto diff --git a/vendor/github.com/moby/buildkit/util/system/path.go b/vendor/github.com/moby/buildkit/util/system/path.go index cdfff68007..14f02b495c 100644 --- a/vendor/github.com/moby/buildkit/util/system/path.go +++ b/vendor/github.com/moby/buildkit/util/system/path.go @@ -16,7 +16,7 @@ const DefaultPathEnvUnix = "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/s // DefaultPathEnvWindows is windows style list of directories to search for // executables. Each directory is separated from the next by a colon // ';' character . -const DefaultPathEnvWindows = "c:\\Windows\\System32;c:\\Windows" +const DefaultPathEnvWindows = "c:\\Windows\\System32;c:\\Windows;C:\\Windows\\System32\\WindowsPowerShell\\v1.0" func DefaultPathEnv(os string) string { if os == "windows" { diff --git a/vendor/github.com/moby/buildkit/util/windows/util_windows.go b/vendor/github.com/moby/buildkit/util/windows/util_windows.go index 135968a6fa..997c19f32b 100644 --- a/vendor/github.com/moby/buildkit/util/windows/util_windows.go +++ b/vendor/github.com/moby/buildkit/util/windows/util_windows.go @@ -7,7 +7,7 @@ import ( "strings" "syscall" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/mount" "github.com/docker/docker/pkg/idtools" "github.com/moby/buildkit/executor" "github.com/moby/buildkit/snapshot" diff --git a/vendor/github.com/moby/buildkit/util/winlayers/applier.go b/vendor/github.com/moby/buildkit/util/winlayers/applier.go index aacfe2c801..6eebbadeff 100644 --- a/vendor/github.com/moby/buildkit/util/winlayers/applier.go +++ b/vendor/github.com/moby/buildkit/util/winlayers/applier.go @@ -8,12 +8,12 @@ import ( "strings" "sync" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/mount" + "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/mount" + "github.com/containerd/containerd/v2/pkg/archive" + "github.com/containerd/containerd/v2/pkg/archive/compression" cerrdefs "github.com/containerd/errdefs" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" diff --git a/vendor/github.com/moby/buildkit/util/winlayers/apply.go b/vendor/github.com/moby/buildkit/util/winlayers/apply.go index ef4b5a49f4..1757bbebbc 100644 --- a/vendor/github.com/moby/buildkit/util/winlayers/apply.go +++ b/vendor/github.com/moby/buildkit/util/winlayers/apply.go @@ -5,8 +5,8 @@ package winlayers import ( "context" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" ) diff --git a/vendor/github.com/moby/buildkit/util/winlayers/apply_nydus.go b/vendor/github.com/moby/buildkit/util/winlayers/apply_nydus.go index c1577a676f..0cbef79ec4 100644 --- a/vendor/github.com/moby/buildkit/util/winlayers/apply_nydus.go +++ b/vendor/github.com/moby/buildkit/util/winlayers/apply_nydus.go @@ -6,9 +6,9 @@ import ( "context" "io" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/archive" digest "github.com/opencontainers/go-digest" ocispecs "github.com/opencontainers/image-spec/specs-go/v1" "github.com/pkg/errors" diff --git a/vendor/github.com/moby/buildkit/util/winlayers/differ.go b/vendor/github.com/moby/buildkit/util/winlayers/differ.go index a669cbab89..f0c3181b41 100644 --- a/vendor/github.com/moby/buildkit/util/winlayers/differ.go +++ b/vendor/github.com/moby/buildkit/util/winlayers/differ.go @@ -9,12 +9,12 @@ import ( "io" "time" - "github.com/containerd/containerd/archive" - "github.com/containerd/containerd/archive/compression" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/labels" - "github.com/containerd/containerd/mount" + "github.com/containerd/containerd/v2/core/content" + "github.com/containerd/containerd/v2/core/diff" + "github.com/containerd/containerd/v2/core/mount" + "github.com/containerd/containerd/v2/pkg/archive" + "github.com/containerd/containerd/v2/pkg/archive/compression" + "github.com/containerd/containerd/v2/pkg/labels" cerrdefs "github.com/containerd/errdefs" log "github.com/moby/buildkit/util/bklog" digest "github.com/opencontainers/go-digest" diff --git a/vendor/github.com/moby/buildkit/worker/base/worker.go b/vendor/github.com/moby/buildkit/worker/base/worker.go index 3f3a77c8be..ffe78f6ec6 100644 --- a/vendor/github.com/moby/buildkit/worker/base/worker.go +++ b/vendor/github.com/moby/buildkit/worker/base/worker.go @@ -7,11 +7,11 @@ import ( "path/filepath" "time" - "github.com/containerd/containerd/content" - "github.com/containerd/containerd/diff" - "github.com/containerd/containerd/gc" - "github.com/containerd/containerd/images" - "github.com/containerd/containerd/remotes/docker" + "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/remotes/docker" + "github.com/containerd/containerd/v2/pkg/gc" "github.com/containerd/platforms" "github.com/docker/docker/pkg/idtools" "github.com/hashicorp/go-multierror" diff --git a/vendor/github.com/moby/buildkit/worker/containerd/containerd.go b/vendor/github.com/moby/buildkit/worker/containerd/containerd.go index 399b7def5b..31f5e01b03 100644 --- a/vendor/github.com/moby/buildkit/worker/containerd/containerd.go +++ b/vendor/github.com/moby/buildkit/worker/containerd/containerd.go @@ -7,10 +7,9 @@ import ( "strconv" "strings" - "github.com/containerd/containerd" - "github.com/containerd/containerd/gc" - "github.com/containerd/containerd/leases" - ptypes "github.com/containerd/containerd/protobuf/types" + ctd "github.com/containerd/containerd/v2/client" + "github.com/containerd/containerd/v2/core/leases" + "github.com/containerd/containerd/v2/pkg/gc" "github.com/containerd/platforms" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/cache/metadata" @@ -47,16 +46,16 @@ type WorkerOptions struct { } // NewWorkerOpt creates a WorkerOpt. -func NewWorkerOpt(workerOpts WorkerOptions, opts ...containerd.ClientOpt) (base.WorkerOpt, error) { - opts = append(opts, containerd.WithDefaultNamespace(workerOpts.Namespace)) - client, err := containerd.New(workerOpts.Address, opts...) +func NewWorkerOpt(workerOpts WorkerOptions, opts ...ctd.Opt) (base.WorkerOpt, error) { + opts = append(opts, ctd.WithDefaultNamespace(workerOpts.Namespace)) + client, err := ctd.New(workerOpts.Address, opts...) if err != nil { return base.WorkerOpt{}, errors.Wrapf(err, "failed to connect client to %q . make sure containerd is running", workerOpts.Address) } return newContainerd(client, workerOpts) } -func newContainerd(client *containerd.Client, workerOpts WorkerOptions) (base.WorkerOpt, error) { +func newContainerd(client *ctd.Client, workerOpts WorkerOptions) (base.WorkerOpt, error) { if strings.Contains(workerOpts.SnapshotterName, "/") { return base.WorkerOpt{}, errors.Errorf("bad snapshotter name: %q", workerOpts.SnapshotterName) } @@ -73,7 +72,7 @@ func newContainerd(client *containerd.Client, workerOpts WorkerOptions) (base.Wo return base.WorkerOpt{}, err } - serverInfo, err := client.IntrospectionService().Server(context.TODO(), &ptypes.Empty{}) + serverInfo, err := client.IntrospectionService().Server(context.TODO()) if err != nil { return base.WorkerOpt{}, err } @@ -115,7 +114,7 @@ func newContainerd(client *containerd.Client, workerOpts WorkerOptions) (base.Wo cs := containerdsnapshot.NewContentStore(client.ContentStore(), workerOpts.Namespace) - resp, err := client.IntrospectionService().Plugins(context.TODO(), []string{"type==io.containerd.runtime.v1", "type==io.containerd.runtime.v2"}) + resp, err := client.IntrospectionService().Plugins(context.TODO(), "type==io.containerd.runtime.v1", "type==io.containerd.runtime.v2") if err != nil { return base.WorkerOpt{}, errors.Wrap(err, "failed to list runtime plugin") } diff --git a/vendor/github.com/moby/buildkit/worker/filter.go b/vendor/github.com/moby/buildkit/worker/filter.go index c94a6265f3..b621b51e87 100644 --- a/vendor/github.com/moby/buildkit/worker/filter.go +++ b/vendor/github.com/moby/buildkit/worker/filter.go @@ -3,7 +3,7 @@ package worker import ( "strings" - "github.com/containerd/containerd/filters" + "github.com/containerd/containerd/v2/pkg/filters" ) func adaptWorker(w Worker) filters.Adaptor { diff --git a/vendor/github.com/moby/buildkit/worker/workercontroller.go b/vendor/github.com/moby/buildkit/worker/workercontroller.go index 150eed352a..1a1b568e21 100644 --- a/vendor/github.com/moby/buildkit/worker/workercontroller.go +++ b/vendor/github.com/moby/buildkit/worker/workercontroller.go @@ -1,7 +1,7 @@ package worker import ( - "github.com/containerd/containerd/filters" + "github.com/containerd/containerd/v2/pkg/filters" "github.com/hashicorp/go-multierror" "github.com/moby/buildkit/cache" "github.com/moby/buildkit/client" diff --git a/vendor/github.com/pelletier/go-toml/v2/.dockerignore b/vendor/github.com/pelletier/go-toml/v2/.dockerignore new file mode 100644 index 0000000000..7b5883475d --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/.dockerignore @@ -0,0 +1,2 @@ +cmd/tomll/tomll +cmd/tomljson/tomljson diff --git a/vendor/github.com/pelletier/go-toml/v2/.gitattributes b/vendor/github.com/pelletier/go-toml/v2/.gitattributes new file mode 100644 index 0000000000..34a0a21a36 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/.gitattributes @@ -0,0 +1,4 @@ +* text=auto + +benchmark/benchmark.toml text eol=lf +testdata/** text eol=lf diff --git a/vendor/github.com/pelletier/go-toml/v2/.gitignore b/vendor/github.com/pelletier/go-toml/v2/.gitignore new file mode 100644 index 0000000000..4b7c4eda3a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/.gitignore @@ -0,0 +1,7 @@ +test_program/test_program_bin +fuzz/ +cmd/tomll/tomll +cmd/tomljson/tomljson +cmd/tomltestgen/tomltestgen +dist +tests/ diff --git a/vendor/github.com/pelletier/go-toml/v2/.golangci.toml b/vendor/github.com/pelletier/go-toml/v2/.golangci.toml new file mode 100644 index 0000000000..067db55174 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/.golangci.toml @@ -0,0 +1,84 @@ +[service] +golangci-lint-version = "1.39.0" + +[linters-settings.wsl] +allow-assign-and-anything = true + +[linters-settings.exhaustive] +default-signifies-exhaustive = true + +[linters] +disable-all = true +enable = [ + "asciicheck", + "bodyclose", + "cyclop", + "deadcode", + "depguard", + "dogsled", + "dupl", + "durationcheck", + "errcheck", + "errorlint", + "exhaustive", + # "exhaustivestruct", + "exportloopref", + "forbidigo", + # "forcetypeassert", + "funlen", + "gci", + # "gochecknoglobals", + "gochecknoinits", + "gocognit", + "goconst", + "gocritic", + "gocyclo", + "godot", + "godox", + # "goerr113", + "gofmt", + "gofumpt", + "goheader", + "goimports", + "golint", + "gomnd", + # "gomoddirectives", + "gomodguard", + "goprintffuncname", + "gosec", + "gosimple", + "govet", + # "ifshort", + "importas", + "ineffassign", + "lll", + "makezero", + "misspell", + "nakedret", + "nestif", + "nilerr", + # "nlreturn", + "noctx", + "nolintlint", + #"paralleltest", + "prealloc", + "predeclared", + "revive", + "rowserrcheck", + "sqlclosecheck", + "staticcheck", + "structcheck", + "stylecheck", + # "testpackage", + "thelper", + "tparallel", + "typecheck", + "unconvert", + "unparam", + "unused", + "varcheck", + "wastedassign", + "whitespace", + # "wrapcheck", + # "wsl" +] diff --git a/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml new file mode 100644 index 0000000000..ec52857a3e --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/.goreleaser.yaml @@ -0,0 +1,127 @@ +version: 2 +before: + hooks: + - go mod tidy + - go fmt ./... + - go test ./... +builds: + - id: tomll + main: ./cmd/tomll + binary: tomll + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} + mod_timestamp: '{{ .CommitTimestamp }}' + targets: + - linux_amd64 + - linux_arm64 + - linux_arm + - linux_riscv64 + - windows_amd64 + - windows_arm64 + - windows_arm + - darwin_amd64 + - darwin_arm64 + - id: tomljson + main: ./cmd/tomljson + binary: tomljson + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} + mod_timestamp: '{{ .CommitTimestamp }}' + targets: + - linux_amd64 + - linux_arm64 + - linux_arm + - linux_riscv64 + - windows_amd64 + - windows_arm64 + - windows_arm + - darwin_amd64 + - darwin_arm64 + - id: jsontoml + main: ./cmd/jsontoml + binary: jsontoml + env: + - CGO_ENABLED=0 + flags: + - -trimpath + ldflags: + - -X main.version={{.Version}} -X main.commit={{.Commit}} -X main.date={{.CommitDate}} + mod_timestamp: '{{ .CommitTimestamp }}' + targets: + - linux_amd64 + - linux_arm64 + - linux_riscv64 + - linux_arm + - windows_amd64 + - windows_arm64 + - windows_arm + - darwin_amd64 + - darwin_arm64 +universal_binaries: + - id: tomll + replace: true + name_template: tomll + - id: tomljson + replace: true + name_template: tomljson + - id: jsontoml + replace: true + name_template: jsontoml +archives: +- id: jsontoml + format: tar.xz + builds: + - jsontoml + files: + - none* + name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}" +- id: tomljson + format: tar.xz + builds: + - tomljson + files: + - none* + name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}" +- id: tomll + format: tar.xz + builds: + - tomll + files: + - none* + name_template: "{{ .Binary }}_{{.Version}}_{{ .Os }}_{{ .Arch }}" +dockers: + - id: tools + goos: linux + goarch: amd64 + ids: + - jsontoml + - tomljson + - tomll + image_templates: + - "ghcr.io/pelletier/go-toml:latest" + - "ghcr.io/pelletier/go-toml:{{ .Tag }}" + - "ghcr.io/pelletier/go-toml:v{{ .Major }}" + skip_push: false +checksum: + name_template: 'sha256sums.txt' +snapshot: + name_template: "{{ incpatch .Version }}-next" +release: + github: + owner: pelletier + name: go-toml + draft: true + prerelease: auto + mode: replace +changelog: + use: github-native +announce: + skip: true diff --git a/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md b/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md new file mode 100644 index 0000000000..96ecf9e2b3 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/CONTRIBUTING.md @@ -0,0 +1,193 @@ +# Contributing + +Thank you for your interest in go-toml! We appreciate you considering +contributing to go-toml! + +The main goal is the project is to provide an easy-to-use and efficient TOML +implementation for Go that gets the job done and gets out of your way – dealing +with TOML is probably not the central piece of your project. + +As the single maintainer of go-toml, time is scarce. All help, big or small, is +more than welcomed! + +## Ask questions + +Any question you may have, somebody else might have it too. Always feel free to +ask them on the [discussion board][discussions]. We will try to answer them as +clearly and quickly as possible, time permitting. + +Asking questions also helps us identify areas where the documentation needs +improvement, or new features that weren't envisioned before. Sometimes, a +seemingly innocent question leads to the fix of a bug. Don't hesitate and ask +away! + +[discussions]: https://github.com/pelletier/go-toml/discussions + +## Improve the documentation + +The best way to share your knowledge and experience with go-toml is to improve +the documentation. Fix a typo, clarify an interface, add an example, anything +goes! + +The documentation is present in the [README][readme] and thorough the source +code. On release, it gets updated on [pkg.go.dev][pkg.go.dev]. To make a change +to the documentation, create a pull request with your proposed changes. For +simple changes like that, the easiest way to go is probably the "Fork this +project and edit the file" button on Github, displayed at the top right of the +file. Unless it's a trivial change (for example a typo), provide a little bit of +context in your pull request description or commit message. + +## Report a bug + +Found a bug! Sorry to hear that :(. Help us and other track them down and fix by +reporting it. [File a new bug report][bug-report] on the [issues +tracker][issues-tracker]. The template should provide enough guidance on what to +include. When in doubt: add more details! By reducing ambiguity and providing +more information, it decreases back and forth and saves everyone time. + +## Code changes + +Want to contribute a patch? Very happy to hear that! + +First, some high-level rules: + +- A short proposal with some POC code is better than a lengthy piece of text + with no code. Code speaks louder than words. That being said, bigger changes + should probably start with a [discussion][discussions]. +- No backward-incompatible patch will be accepted unless discussed. Sometimes + it's hard, but we try not to break people's programs unless we absolutely have + to. +- If you are writing a new feature or extending an existing one, make sure to + write some documentation. +- Bug fixes need to be accompanied with regression tests. +- New code needs to be tested. +- Your commit messages need to explain why the change is needed, even if already + included in the PR description. + +It does sound like a lot, but those best practices are here to save time overall +and continuously improve the quality of the project, which is something everyone +benefits from. + +### Get started + +The fairly standard code contribution process looks like that: + +1. [Fork the project][fork]. +2. Make your changes, commit on any branch you like. +3. [Open up a pull request][pull-request] +4. Review, potential ask for changes. +5. Merge. + +Feel free to ask for help! You can create draft pull requests to gather +some early feedback! + +### Run the tests + +You can run tests for go-toml using Go's test tool: `go test -race ./...`. + +During the pull request process, all tests will be ran on Linux, Windows, and +MacOS on the last two versions of Go. + +However, given GitHub's new policy to _not_ run Actions on pull requests until a +maintainer clicks on button, it is highly recommended that you run them locally +as you make changes. + +### Check coverage + +We use `go tool cover` to compute test coverage. Most code editors have a way to +run and display code coverage, but at the end of the day, we do this: + +``` +go test -covermode=atomic -coverprofile=coverage.out +go tool cover -func=coverage.out +``` + +and verify that the overall percentage of tested code does not go down. This is +a requirement. As a rule of thumb, all lines of code touched by your changes +should be covered. On Unix you can use `./ci.sh coverage -d v2` to check if your +code lowers the coverage. + +### Verify performance + +Go-toml aims to stay efficient. We rely on a set of scenarios executed with Go's +builtin benchmark systems. Because of their noisy nature, containers provided by +Github Actions cannot be reliably used for benchmarking. As a result, you are +responsible for checking that your changes do not incur a performance penalty. +You can run their following to execute benchmarks: + +``` +go test ./... -bench=. -count=10 +``` + +Benchmark results should be compared against each other with +[benchstat][benchstat]. Typical flow looks like this: + +1. On the `v2` branch, run `go test ./... -bench=. -count 10` and save output to + a file (for example `old.txt`). +2. Make some code changes. +3. Run `go test ....` again, and save the output to an other file (for example + `new.txt`). +4. Run `benchstat old.txt new.txt` to check that time/op does not go up in any + test. + +On Unix you can use `./ci.sh benchmark -d v2` to verify how your code impacts +performance. + +It is highly encouraged to add the benchstat results to your pull request +description. Pull requests that lower performance will receive more scrutiny. + +[benchstat]: https://pkg.go.dev/golang.org/x/perf/cmd/benchstat + +### Style + +Try to look around and follow the same format and structure as the rest of the +code. We enforce using `go fmt` on the whole code base. + +--- + +## Maintainers-only + +### Merge pull request + +Checklist: + +- Passing CI. +- Does not introduce backward-incompatible changes (unless discussed). +- Has relevant doc changes. +- Benchstat does not show performance regression. +- Pull request is [labeled appropriately][pr-labels]. +- Title will be understandable in the changelog. + +1. Merge using "squash and merge". +2. Make sure to edit the commit message to keep all the useful information + nice and clean. +3. Make sure the commit title is clear and contains the PR number (#123). + +### New release + +1. Decide on the next version number. Use semver. Review commits since last + version to assess. +2. Tag release. For example: +``` +git checkout v2 +git pull +git tag v2.2.0 +git push --tags +``` +3. CI automatically builds a draft Github release. Review it and edit as + necessary. Look for "Other changes". That would indicate a pull request not + labeled properly. Tweak labels and pull request titles until changelog looks + good for users. +4. Check "create discussion" box, in the "Releases" category. +5. If new version is an alpha or beta only, check pre-release box. + + +[issues-tracker]: https://github.com/pelletier/go-toml/issues +[bug-report]: https://github.com/pelletier/go-toml/issues/new?template=bug_report.md +[pkg.go.dev]: https://pkg.go.dev/github.com/pelletier/go-toml +[readme]: ./README.md +[fork]: https://help.github.com/articles/fork-a-repo +[pull-request]: https://help.github.com/en/articles/creating-a-pull-request +[new-release]: https://github.com/pelletier/go-toml/releases/new +[gh]: https://github.com/cli/cli +[pr-labels]: https://github.com/pelletier/go-toml/blob/v2/.github/release.yml diff --git a/vendor/github.com/pelletier/go-toml/v2/Dockerfile b/vendor/github.com/pelletier/go-toml/v2/Dockerfile new file mode 100644 index 0000000000..b9e9332379 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/Dockerfile @@ -0,0 +1,5 @@ +FROM scratch +ENV PATH "$PATH:/bin" +COPY tomll /bin/tomll +COPY tomljson /bin/tomljson +COPY jsontoml /bin/jsontoml diff --git a/vendor/github.com/pelletier/go-toml/v2/LICENSE b/vendor/github.com/pelletier/go-toml/v2/LICENSE new file mode 100644 index 0000000000..991e2ae966 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/LICENSE @@ -0,0 +1,22 @@ +The MIT License (MIT) + +go-toml v2 +Copyright (c) 2021 - 2023 Thomas Pelletier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/pelletier/go-toml/v2/README.md b/vendor/github.com/pelletier/go-toml/v2/README.md new file mode 100644 index 0000000000..0755e55642 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/README.md @@ -0,0 +1,576 @@ +# go-toml v2 + +Go library for the [TOML](https://toml.io/en/) format. + +This library supports [TOML v1.0.0](https://toml.io/en/v1.0.0). + +[🐞 Bug Reports](https://github.com/pelletier/go-toml/issues) + +[💬 Anything else](https://github.com/pelletier/go-toml/discussions) + +## Documentation + +Full API, examples, and implementation notes are available in the Go +documentation. + +[![Go Reference](https://pkg.go.dev/badge/github.com/pelletier/go-toml/v2.svg)](https://pkg.go.dev/github.com/pelletier/go-toml/v2) + +## Import + +```go +import "github.com/pelletier/go-toml/v2" +``` + +See [Modules](#Modules). + +## Features + +### Stdlib behavior + +As much as possible, this library is designed to behave similarly as the +standard library's `encoding/json`. + +### Performance + +While go-toml favors usability, it is written with performance in mind. Most +operations should not be shockingly slow. See [benchmarks](#benchmarks). + +### Strict mode + +`Decoder` can be set to "strict mode", which makes it error when some parts of +the TOML document was not present in the target structure. This is a great way +to check for typos. [See example in the documentation][strict]. + +[strict]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Decoder.DisallowUnknownFields + +### Contextualized errors + +When most decoding errors occur, go-toml returns [`DecodeError`][decode-err], +which contains a human readable contextualized version of the error. For +example: + +``` +1| [server] +2| path = 100 + | ~~~ cannot decode TOML integer into struct field toml_test.Server.Path of type string +3| port = 50 +``` + +[decode-err]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#DecodeError + +### Local date and time support + +TOML supports native [local date/times][ldt]. It allows to represent a given +date, time, or date-time without relation to a timezone or offset. To support +this use-case, go-toml provides [`LocalDate`][tld], [`LocalTime`][tlt], and +[`LocalDateTime`][tldt]. Those types can be transformed to and from `time.Time`, +making them convenient yet unambiguous structures for their respective TOML +representation. + +[ldt]: https://toml.io/en/v1.0.0#local-date-time +[tld]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDate +[tlt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalTime +[tldt]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#LocalDateTime + +### Commented config + +Since TOML is often used for configuration files, go-toml can emit documents +annotated with [comments and commented-out values][comments-example]. For +example, it can generate the following file: + +```toml +# Host IP to connect to. +host = '127.0.0.1' +# Port of the remote server. +port = 4242 + +# Encryption parameters (optional) +# [TLS] +# cipher = 'AEAD-AES128-GCM-SHA256' +# version = 'TLS 1.3' +``` + +[comments-example]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#example-Marshal-Commented + +## Getting started + +Given the following struct, let's see how to read it and write it as TOML: + +```go +type MyConfig struct { + Version int + Name string + Tags []string +} +``` + +### Unmarshaling + +[`Unmarshal`][unmarshal] reads a TOML document and fills a Go structure with its +content. For example: + +```go +doc := ` +version = 2 +name = "go-toml" +tags = ["go", "toml"] +` + +var cfg MyConfig +err := toml.Unmarshal([]byte(doc), &cfg) +if err != nil { + panic(err) +} +fmt.Println("version:", cfg.Version) +fmt.Println("name:", cfg.Name) +fmt.Println("tags:", cfg.Tags) + +// Output: +// version: 2 +// name: go-toml +// tags: [go toml] +``` + +[unmarshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Unmarshal + +### Marshaling + +[`Marshal`][marshal] is the opposite of Unmarshal: it represents a Go structure +as a TOML document: + +```go +cfg := MyConfig{ + Version: 2, + Name: "go-toml", + Tags: []string{"go", "toml"}, +} + +b, err := toml.Marshal(cfg) +if err != nil { + panic(err) +} +fmt.Println(string(b)) + +// Output: +// Version = 2 +// Name = 'go-toml' +// Tags = ['go', 'toml'] +``` + +[marshal]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Marshal + +## Unstable API + +This API does not yet follow the backward compatibility guarantees of this +library. They provide early access to features that may have rough edges or an +API subject to change. + +### Parser + +Parser is the unstable API that allows iterative parsing of a TOML document at +the AST level. See https://pkg.go.dev/github.com/pelletier/go-toml/v2/unstable. + +## Benchmarks + +Execution time speedup compared to other Go TOML libraries: + + + + + + + + + + + + + +
Benchmarkgo-toml v1BurntSushi/toml
Marshal/HugoFrontMatter-21.9x2.2x
Marshal/ReferenceFile/map-21.7x2.1x
Marshal/ReferenceFile/struct-22.2x3.0x
Unmarshal/HugoFrontMatter-22.9x2.7x
Unmarshal/ReferenceFile/map-22.6x2.7x
Unmarshal/ReferenceFile/struct-24.6x5.1x
+
See more +

The table above has the results of the most common use-cases. The table below +contains the results of all benchmarks, including unrealistic ones. It is +provided for completeness.

+ + + + + + + + + + + + + + + + + + +
Benchmarkgo-toml v1BurntSushi/toml
Marshal/SimpleDocument/map-21.8x2.7x
Marshal/SimpleDocument/struct-22.7x3.8x
Unmarshal/SimpleDocument/map-23.8x3.0x
Unmarshal/SimpleDocument/struct-25.6x4.1x
UnmarshalDataset/example-23.0x3.2x
UnmarshalDataset/code-22.3x2.9x
UnmarshalDataset/twitter-22.6x2.7x
UnmarshalDataset/citm_catalog-22.2x2.3x
UnmarshalDataset/canada-21.8x1.5x
UnmarshalDataset/config-24.1x2.9x
geomean2.7x2.8x
+

This table can be generated with ./ci.sh benchmark -a -html.

+
+ +## Modules + +go-toml uses Go's standard modules system. + +Installation instructions: + +- Go ≥ 1.16: Nothing to do. Use the import in your code. The `go` command deals + with it automatically. +- Go ≥ 1.13: `GO111MODULE=on go get github.com/pelletier/go-toml/v2`. + +In case of trouble: [Go Modules FAQ][mod-faq]. + +[mod-faq]: https://github.com/golang/go/wiki/Modules#why-does-installing-a-tool-via-go-get-fail-with-error-cannot-find-main-module + +## Tools + +Go-toml provides three handy command line tools: + + * `tomljson`: Reads a TOML file and outputs its JSON representation. + + ``` + $ go install github.com/pelletier/go-toml/v2/cmd/tomljson@latest + $ tomljson --help + ``` + + * `jsontoml`: Reads a JSON file and outputs a TOML representation. + + ``` + $ go install github.com/pelletier/go-toml/v2/cmd/jsontoml@latest + $ jsontoml --help + ``` + + * `tomll`: Lints and reformats a TOML file. + + ``` + $ go install github.com/pelletier/go-toml/v2/cmd/tomll@latest + $ tomll --help + ``` + +### Docker image + +Those tools are also available as a [Docker image][docker]. For example, to use +`tomljson`: + +``` +docker run -i ghcr.io/pelletier/go-toml:v2 tomljson < example.toml +``` + +Multiple versions are available on [ghcr.io][docker]. + +[docker]: https://github.com/pelletier/go-toml/pkgs/container/go-toml + +## Migrating from v1 + +This section describes the differences between v1 and v2, with some pointers on +how to get the original behavior when possible. + +### Decoding / Unmarshal + +#### Automatic field name guessing + +When unmarshaling to a struct, if a key in the TOML document does not exactly +match the name of a struct field or any of the `toml`-tagged field, v1 tries +multiple variations of the key ([code][v1-keys]). + +V2 instead does a case-insensitive matching, like `encoding/json`. + +This could impact you if you are relying on casing to differentiate two fields, +and one of them is a not using the `toml` struct tag. The recommended solution +is to be specific about tag names for those fields using the `toml` struct tag. + +[v1-keys]: https://github.com/pelletier/go-toml/blob/a2e52561804c6cd9392ebf0048ca64fe4af67a43/marshal.go#L775-L781 + +#### Ignore preexisting value in interface + +When decoding into a non-nil `interface{}`, go-toml v1 uses the type of the +element in the interface to decode the object. For example: + +```go +type inner struct { + B interface{} +} +type doc struct { + A interface{} +} + +d := doc{ + A: inner{ + B: "Before", + }, +} + +data := ` +[A] +B = "After" +` + +toml.Unmarshal([]byte(data), &d) +fmt.Printf("toml v1: %#v\n", d) + +// toml v1: main.doc{A:main.inner{B:"After"}} +``` + +In this case, field `A` is of type `interface{}`, containing a `inner` struct. +V1 sees that type and uses it when decoding the object. + +When decoding an object into an `interface{}`, V2 instead disregards whatever +value the `interface{}` may contain and replaces it with a +`map[string]interface{}`. With the same data structure as above, here is what +the result looks like: + +```go +toml.Unmarshal([]byte(data), &d) +fmt.Printf("toml v2: %#v\n", d) + +// toml v2: main.doc{A:map[string]interface {}{"B":"After"}} +``` + +This is to match `encoding/json`'s behavior. There is no way to make the v2 +decoder behave like v1. + +#### Values out of array bounds ignored + +When decoding into an array, v1 returns an error when the number of elements +contained in the doc is superior to the capacity of the array. For example: + +```go +type doc struct { + A [2]string +} +d := doc{} +err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d) +fmt.Println(err) + +// (1, 1): unmarshal: TOML array length (3) exceeds destination array length (2) +``` + +In the same situation, v2 ignores the last value: + +```go +err := toml.Unmarshal([]byte(`A = ["one", "two", "many"]`), &d) +fmt.Println("err:", err, "d:", d) +// err: d: {[one two]} +``` + +This is to match `encoding/json`'s behavior. There is no way to make the v2 +decoder behave like v1. + +#### Support for `toml.Unmarshaler` has been dropped + +This method was not widely used, poorly defined, and added a lot of complexity. +A similar effect can be achieved by implementing the `encoding.TextUnmarshaler` +interface and use strings. + +#### Support for `default` struct tag has been dropped + +This feature adds complexity and a poorly defined API for an effect that can be +accomplished outside of the library. + +It does not seem like other format parsers in Go support that feature (the +project referenced in the original ticket #202 has not been updated since 2017). +Given that go-toml v2 should not touch values not in the document, the same +effect can be achieved by pre-filling the struct with defaults (libraries like +[go-defaults][go-defaults] can help). Also, string representation is not well +defined for all types: it creates issues like #278. + +The recommended replacement is pre-filling the struct before unmarshaling. + +[go-defaults]: https://github.com/mcuadros/go-defaults + +#### `toml.Tree` replacement + +This structure was the initial attempt at providing a document model for +go-toml. It allows manipulating the structure of any document, encoding and +decoding from their TOML representation. While a more robust feature was +initially planned in go-toml v2, this has been ultimately [removed from +scope][nodoc] of this library, with no plan to add it back at the moment. The +closest equivalent at the moment would be to unmarshal into an `interface{}` and +use type assertions and/or reflection to manipulate the arbitrary +structure. However this would fall short of providing all of the TOML features +such as adding comments and be specific about whitespace. + + +#### `toml.Position` are not retrievable anymore + +The API for retrieving the position (line, column) of a specific TOML element do +not exist anymore. This was done to minimize the amount of concepts introduced +by the library (query path), and avoid the performance hit related to storing +positions in the absence of a document model, for a feature that seemed to have +little use. Errors however have gained more detailed position +information. Position retrieval seems better fitted for a document model, which +has been [removed from the scope][nodoc] of go-toml v2 at the moment. + +### Encoding / Marshal + +#### Default struct fields order + +V1 emits struct fields order alphabetically by default. V2 struct fields are +emitted in order they are defined. For example: + +```go +type S struct { + B string + A string +} + +data := S{ + B: "B", + A: "A", +} + +b, _ := tomlv1.Marshal(data) +fmt.Println("v1:\n" + string(b)) + +b, _ = tomlv2.Marshal(data) +fmt.Println("v2:\n" + string(b)) + +// Output: +// v1: +// A = "A" +// B = "B" + +// v2: +// B = 'B' +// A = 'A' +``` + +There is no way to make v2 encoder behave like v1. A workaround could be to +manually sort the fields alphabetically in the struct definition, or generate +struct types using `reflect.StructOf`. + +#### No indentation by default + +V1 automatically indents content of tables by default. V2 does not. However the +same behavior can be obtained using [`Encoder.SetIndentTables`][sit]. For example: + +```go +data := map[string]interface{}{ + "table": map[string]string{ + "key": "value", + }, +} + +b, _ := tomlv1.Marshal(data) +fmt.Println("v1:\n" + string(b)) + +b, _ = tomlv2.Marshal(data) +fmt.Println("v2:\n" + string(b)) + +buf := bytes.Buffer{} +enc := tomlv2.NewEncoder(&buf) +enc.SetIndentTables(true) +enc.Encode(data) +fmt.Println("v2 Encoder:\n" + string(buf.Bytes())) + +// Output: +// v1: +// +// [table] +// key = "value" +// +// v2: +// [table] +// key = 'value' +// +// +// v2 Encoder: +// [table] +// key = 'value' +``` + +[sit]: https://pkg.go.dev/github.com/pelletier/go-toml/v2#Encoder.SetIndentTables + +#### Keys and strings are single quoted + +V1 always uses double quotes (`"`) around strings and keys that cannot be +represented bare (unquoted). V2 uses single quotes instead by default (`'`), +unless a character cannot be represented, then falls back to double quotes. As a +result of this change, `Encoder.QuoteMapKeys` has been removed, as it is not +useful anymore. + +There is no way to make v2 encoder behave like v1. + +#### `TextMarshaler` emits as a string, not TOML + +Types that implement [`encoding.TextMarshaler`][tm] can emit arbitrary TOML in +v1. The encoder would append the result to the output directly. In v2 the result +is wrapped in a string. As a result, this interface cannot be implemented by the +root object. + +There is no way to make v2 encoder behave like v1. + +[tm]: https://golang.org/pkg/encoding/#TextMarshaler + +#### `Encoder.CompactComments` has been removed + +Emitting compact comments is now the default behavior of go-toml. This option +is not necessary anymore. + +#### Struct tags have been merged + +V1 used to provide multiple struct tags: `comment`, `commented`, `multiline`, +`toml`, and `omitempty`. To behave more like the standard library, v2 has merged +`toml`, `multiline`, `commented`, and `omitempty`. For example: + +```go +type doc struct { + // v1 + F string `toml:"field" multiline:"true" omitempty:"true" commented:"true"` + // v2 + F string `toml:"field,multiline,omitempty,commented"` +} +``` + +Has a result, the `Encoder.SetTag*` methods have been removed, as there is just +one tag now. + +#### `Encoder.ArraysWithOneElementPerLine` has been renamed + +The new name is `Encoder.SetArraysMultiline`. The behavior should be the same. + +#### `Encoder.Indentation` has been renamed + +The new name is `Encoder.SetIndentSymbol`. The behavior should be the same. + + +#### Embedded structs behave like stdlib + +V1 defaults to merging embedded struct fields into the embedding struct. This +behavior was unexpected because it does not follow the standard library. To +avoid breaking backward compatibility, the `Encoder.PromoteAnonymous` method was +added to make the encoder behave correctly. Given backward compatibility is not +a problem anymore, v2 does the right thing by default: it follows the behavior +of `encoding/json`. `Encoder.PromoteAnonymous` has been removed. + +[nodoc]: https://github.com/pelletier/go-toml/discussions/506#discussioncomment-1526038 + +### `query` + +go-toml v1 provided the [`go-toml/query`][query] package. It allowed to run +JSONPath-style queries on TOML files. This feature is not available in v2. For a +replacement, check out [dasel][dasel]. + +This package has been removed because it was essentially not supported anymore +(last commit May 2020), increased the complexity of the code base, and more +complete solutions exist out there. + +[query]: https://github.com/pelletier/go-toml/tree/f99d6bbca119636aeafcf351ee52b3d202782627/query +[dasel]: https://github.com/TomWright/dasel + +## Versioning + +Expect for parts explicitly marked otherwise, go-toml follows [Semantic +Versioning](https://semver.org). The supported version of +[TOML](https://github.com/toml-lang/toml) is indicated at the beginning of this +document. The last two major versions of Go are supported (see [Go Release +Policy](https://golang.org/doc/devel/release.html#policy)). + +## License + +The MIT License (MIT). Read [LICENSE](LICENSE). diff --git a/vendor/github.com/pelletier/go-toml/v2/SECURITY.md b/vendor/github.com/pelletier/go-toml/v2/SECURITY.md new file mode 100644 index 0000000000..d4d554fda9 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/SECURITY.md @@ -0,0 +1,16 @@ +# Security Policy + +## Supported Versions + +| Version | Supported | +| ---------- | ------------------ | +| Latest 2.x | :white_check_mark: | +| All 1.x | :x: | +| All 0.x | :x: | + +## Reporting a Vulnerability + +Email a vulnerability report to `security@pelletier.codes`. Make sure to include +as many details as possible to reproduce the vulnerability. This is a +side-project: I will try to get back to you as quickly as possible, time +permitting in my personal life. Providing a working patch helps very much! diff --git a/vendor/github.com/pelletier/go-toml/v2/ci.sh b/vendor/github.com/pelletier/go-toml/v2/ci.sh new file mode 100644 index 0000000000..86217a9b09 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/ci.sh @@ -0,0 +1,284 @@ +#!/usr/bin/env bash + + +stderr() { + echo "$@" 1>&2 +} + +usage() { + b=$(basename "$0") + echo $b: ERROR: "$@" 1>&2 + + cat 1>&2 < coverage.out + go tool cover -func=coverage.out + echo "Coverage profile for ${branch}: ${dir}/coverage.out" >&2 + popd + + if [ "${branch}" != "HEAD" ]; then + git worktree remove --force "$dir" + fi +} + +coverage() { + case "$1" in + -d) + shift + target="${1?Need to provide a target branch argument}" + + output_dir="$(mktemp -d)" + target_out="${output_dir}/target.txt" + head_out="${output_dir}/head.txt" + + cover "${target}" > "${target_out}" + cover "HEAD" > "${head_out}" + + cat "${target_out}" + cat "${head_out}" + + echo "" + + target_pct="$(tail -n2 ${target_out} | head -n1 | sed -E 's/.*total.*\t([0-9.]+)%.*/\1/')" + head_pct="$(tail -n2 ${head_out} | head -n1 | sed -E 's/.*total.*\t([0-9.]+)%/\1/')" + echo "Results: ${target} ${target_pct}% HEAD ${head_pct}%" + + delta_pct=$(echo "$head_pct - $target_pct" | bc -l) + echo "Delta: ${delta_pct}" + + if [[ $delta_pct = \-* ]]; then + echo "Regression!"; + + target_diff="${output_dir}/target.diff.txt" + head_diff="${output_dir}/head.diff.txt" + cat "${target_out}" | grep -E '^github.com/pelletier/go-toml' | tr -s "\t " | cut -f 2,3 | sort > "${target_diff}" + cat "${head_out}" | grep -E '^github.com/pelletier/go-toml' | tr -s "\t " | cut -f 2,3 | sort > "${head_diff}" + + diff --side-by-side --suppress-common-lines "${target_diff}" "${head_diff}" + return 1 + fi + return 0 + ;; + esac + + cover "${1-HEAD}" +} + +bench() { + branch="${1}" + out="${2}" + replace="${3}" + dir="$(mktemp -d)" + + stderr "Executing benchmark for ${branch} at ${dir}" + + if [ "${branch}" = "HEAD" ]; then + cp -r . "${dir}/" + else + git worktree add "$dir" "$branch" + fi + + pushd "$dir" + + if [ "${replace}" != "" ]; then + find ./benchmark/ -iname '*.go' -exec sed -i -E "s|github.com/pelletier/go-toml/v2|${replace}|g" {} \; + go get "${replace}" + fi + + export GOMAXPROCS=2 + go test '-bench=^Benchmark(Un)?[mM]arshal' -count=10 -run=Nothing ./... | tee "${out}" + popd + + if [ "${branch}" != "HEAD" ]; then + git worktree remove --force "$dir" + fi +} + +fmktemp() { + if mktemp --version &> /dev/null; then + # GNU + mktemp --suffix=-$1 + else + # BSD + mktemp -t $1 + fi +} + +benchstathtml() { +python3 - $1 <<'EOF' +import sys + +lines = [] +stop = False + +with open(sys.argv[1]) as f: + for line in f.readlines(): + line = line.strip() + if line == "": + stop = True + if not stop: + lines.append(line.split(',')) + +results = [] +for line in reversed(lines[2:]): + if len(line) < 8 or line[0] == "": + continue + v2 = float(line[1]) + results.append([ + line[0].replace("-32", ""), + "%.1fx" % (float(line[3])/v2), # v1 + "%.1fx" % (float(line[7])/v2), # bs + ]) +# move geomean to the end +results.append(results[0]) +del results[0] + + +def printtable(data): + print(""" + + + + + """) + + for r in data: + print(" ".format(*r)) + + print(""" +
Benchmarkgo-toml v1BurntSushi/toml
{}{}{}
""") + + +def match(x): + return "ReferenceFile" in x[0] or "HugoFrontMatter" in x[0] + +above = [x for x in results if match(x)] +below = [x for x in results if not match(x)] + +printtable(above) +print("
See more") +print("""

The table above has the results of the most common use-cases. The table below +contains the results of all benchmarks, including unrealistic ones. It is +provided for completeness.

""") +printtable(below) +print('

This table can be generated with ./ci.sh benchmark -a -html.

') +print("
") + +EOF +} + +benchmark() { + case "$1" in + -d) + shift + target="${1?Need to provide a target branch argument}" + + old=`fmktemp ${target}` + bench "${target}" "${old}" + + new=`fmktemp HEAD` + bench HEAD "${new}" + + benchstat "${old}" "${new}" + return 0 + ;; + -a) + shift + + v2stats=`fmktemp go-toml-v2` + bench HEAD "${v2stats}" "github.com/pelletier/go-toml/v2" + v1stats=`fmktemp go-toml-v1` + bench HEAD "${v1stats}" "github.com/pelletier/go-toml" + bsstats=`fmktemp bs-toml` + bench HEAD "${bsstats}" "github.com/BurntSushi/toml" + + cp "${v2stats}" go-toml-v2.txt + cp "${v1stats}" go-toml-v1.txt + cp "${bsstats}" bs-toml.txt + + if [ "$1" = "-html" ]; then + tmpcsv=`fmktemp csv` + benchstat -format csv go-toml-v2.txt go-toml-v1.txt bs-toml.txt > $tmpcsv + benchstathtml $tmpcsv + else + benchstat go-toml-v2.txt go-toml-v1.txt bs-toml.txt + fi + + rm -f go-toml-v2.txt go-toml-v1.txt bs-toml.txt + return $? + esac + + bench "${1-HEAD}" `mktemp` +} + +case "$1" in + coverage) shift; coverage $@;; + benchmark) shift; benchmark $@;; + *) usage "bad argument $1";; +esac diff --git a/vendor/github.com/pelletier/go-toml/v2/decode.go b/vendor/github.com/pelletier/go-toml/v2/decode.go new file mode 100644 index 0000000000..f0ec3b1705 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/decode.go @@ -0,0 +1,550 @@ +package toml + +import ( + "fmt" + "math" + "strconv" + "time" + + "github.com/pelletier/go-toml/v2/unstable" +) + +func parseInteger(b []byte) (int64, error) { + if len(b) > 2 && b[0] == '0' { + switch b[1] { + case 'x': + return parseIntHex(b) + case 'b': + return parseIntBin(b) + case 'o': + return parseIntOct(b) + default: + panic(fmt.Errorf("invalid base '%c', should have been checked by scanIntOrFloat", b[1])) + } + } + + return parseIntDec(b) +} + +func parseLocalDate(b []byte) (LocalDate, error) { + // full-date = date-fullyear "-" date-month "-" date-mday + // date-fullyear = 4DIGIT + // date-month = 2DIGIT ; 01-12 + // date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year + var date LocalDate + + if len(b) != 10 || b[4] != '-' || b[7] != '-' { + return date, unstable.NewParserError(b, "dates are expected to have the format YYYY-MM-DD") + } + + var err error + + date.Year, err = parseDecimalDigits(b[0:4]) + if err != nil { + return LocalDate{}, err + } + + date.Month, err = parseDecimalDigits(b[5:7]) + if err != nil { + return LocalDate{}, err + } + + date.Day, err = parseDecimalDigits(b[8:10]) + if err != nil { + return LocalDate{}, err + } + + if !isValidDate(date.Year, date.Month, date.Day) { + return LocalDate{}, unstable.NewParserError(b, "impossible date") + } + + return date, nil +} + +func parseDecimalDigits(b []byte) (int, error) { + v := 0 + + for i, c := range b { + if c < '0' || c > '9' { + return 0, unstable.NewParserError(b[i:i+1], "expected digit (0-9)") + } + v *= 10 + v += int(c - '0') + } + + return v, nil +} + +func parseDateTime(b []byte) (time.Time, error) { + // offset-date-time = full-date time-delim full-time + // full-time = partial-time time-offset + // time-offset = "Z" / time-numoffset + // time-numoffset = ( "+" / "-" ) time-hour ":" time-minute + + dt, b, err := parseLocalDateTime(b) + if err != nil { + return time.Time{}, err + } + + var zone *time.Location + + if len(b) == 0 { + // parser should have checked that when assigning the date time node + panic("date time should have a timezone") + } + + if b[0] == 'Z' || b[0] == 'z' { + b = b[1:] + zone = time.UTC + } else { + const dateTimeByteLen = 6 + if len(b) != dateTimeByteLen { + return time.Time{}, unstable.NewParserError(b, "invalid date-time timezone") + } + var direction int + switch b[0] { + case '-': + direction = -1 + case '+': + direction = +1 + default: + return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset character") + } + + if b[3] != ':' { + return time.Time{}, unstable.NewParserError(b[3:4], "expected a : separator") + } + + hours, err := parseDecimalDigits(b[1:3]) + if err != nil { + return time.Time{}, err + } + if hours > 23 { + return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset hours") + } + + minutes, err := parseDecimalDigits(b[4:6]) + if err != nil { + return time.Time{}, err + } + if minutes > 59 { + return time.Time{}, unstable.NewParserError(b[:1], "invalid timezone offset minutes") + } + + seconds := direction * (hours*3600 + minutes*60) + if seconds == 0 { + zone = time.UTC + } else { + zone = time.FixedZone("", seconds) + } + b = b[dateTimeByteLen:] + } + + if len(b) > 0 { + return time.Time{}, unstable.NewParserError(b, "extra bytes at the end of the timezone") + } + + t := time.Date( + dt.Year, + time.Month(dt.Month), + dt.Day, + dt.Hour, + dt.Minute, + dt.Second, + dt.Nanosecond, + zone) + + return t, nil +} + +func parseLocalDateTime(b []byte) (LocalDateTime, []byte, error) { + var dt LocalDateTime + + const localDateTimeByteMinLen = 11 + if len(b) < localDateTimeByteMinLen { + return dt, nil, unstable.NewParserError(b, "local datetimes are expected to have the format YYYY-MM-DDTHH:MM:SS[.NNNNNNNNN]") + } + + date, err := parseLocalDate(b[:10]) + if err != nil { + return dt, nil, err + } + dt.LocalDate = date + + sep := b[10] + if sep != 'T' && sep != ' ' && sep != 't' { + return dt, nil, unstable.NewParserError(b[10:11], "datetime separator is expected to be T or a space") + } + + t, rest, err := parseLocalTime(b[11:]) + if err != nil { + return dt, nil, err + } + dt.LocalTime = t + + return dt, rest, nil +} + +// parseLocalTime is a bit different because it also returns the remaining +// []byte that is didn't need. This is to allow parseDateTime to parse those +// remaining bytes as a timezone. +func parseLocalTime(b []byte) (LocalTime, []byte, error) { + var ( + nspow = [10]int{0, 1e8, 1e7, 1e6, 1e5, 1e4, 1e3, 1e2, 1e1, 1e0} + t LocalTime + ) + + // check if b matches to have expected format HH:MM:SS[.NNNNNN] + const localTimeByteLen = 8 + if len(b) < localTimeByteLen { + return t, nil, unstable.NewParserError(b, "times are expected to have the format HH:MM:SS[.NNNNNN]") + } + + var err error + + t.Hour, err = parseDecimalDigits(b[0:2]) + if err != nil { + return t, nil, err + } + + if t.Hour > 23 { + return t, nil, unstable.NewParserError(b[0:2], "hour cannot be greater 23") + } + if b[2] != ':' { + return t, nil, unstable.NewParserError(b[2:3], "expecting colon between hours and minutes") + } + + t.Minute, err = parseDecimalDigits(b[3:5]) + if err != nil { + return t, nil, err + } + if t.Minute > 59 { + return t, nil, unstable.NewParserError(b[3:5], "minutes cannot be greater 59") + } + if b[5] != ':' { + return t, nil, unstable.NewParserError(b[5:6], "expecting colon between minutes and seconds") + } + + t.Second, err = parseDecimalDigits(b[6:8]) + if err != nil { + return t, nil, err + } + + if t.Second > 60 { + return t, nil, unstable.NewParserError(b[6:8], "seconds cannot be greater 60") + } + + b = b[8:] + + if len(b) >= 1 && b[0] == '.' { + frac := 0 + precision := 0 + digits := 0 + + for i, c := range b[1:] { + if !isDigit(c) { + if i == 0 { + return t, nil, unstable.NewParserError(b[0:1], "need at least one digit after fraction point") + } + break + } + digits++ + + const maxFracPrecision = 9 + if i >= maxFracPrecision { + // go-toml allows decoding fractional seconds + // beyond the supported precision of 9 + // digits. It truncates the fractional component + // to the supported precision and ignores the + // remaining digits. + // + // https://github.com/pelletier/go-toml/discussions/707 + continue + } + + frac *= 10 + frac += int(c - '0') + precision++ + } + + if precision == 0 { + return t, nil, unstable.NewParserError(b[:1], "nanoseconds need at least one digit") + } + + t.Nanosecond = frac * nspow[precision] + t.Precision = precision + + return t, b[1+digits:], nil + } + return t, b, nil +} + +//nolint:cyclop +func parseFloat(b []byte) (float64, error) { + if len(b) == 4 && (b[0] == '+' || b[0] == '-') && b[1] == 'n' && b[2] == 'a' && b[3] == 'n' { + return math.NaN(), nil + } + + cleaned, err := checkAndRemoveUnderscoresFloats(b) + if err != nil { + return 0, err + } + + if cleaned[0] == '.' { + return 0, unstable.NewParserError(b, "float cannot start with a dot") + } + + if cleaned[len(cleaned)-1] == '.' { + return 0, unstable.NewParserError(b, "float cannot end with a dot") + } + + dotAlreadySeen := false + for i, c := range cleaned { + if c == '.' { + if dotAlreadySeen { + return 0, unstable.NewParserError(b[i:i+1], "float can have at most one decimal point") + } + if !isDigit(cleaned[i-1]) { + return 0, unstable.NewParserError(b[i-1:i+1], "float decimal point must be preceded by a digit") + } + if !isDigit(cleaned[i+1]) { + return 0, unstable.NewParserError(b[i:i+2], "float decimal point must be followed by a digit") + } + dotAlreadySeen = true + } + } + + start := 0 + if cleaned[0] == '+' || cleaned[0] == '-' { + start = 1 + } + if cleaned[start] == '0' && len(cleaned) > start+1 && isDigit(cleaned[start+1]) { + return 0, unstable.NewParserError(b, "float integer part cannot have leading zeroes") + } + + f, err := strconv.ParseFloat(string(cleaned), 64) + if err != nil { + return 0, unstable.NewParserError(b, "unable to parse float: %w", err) + } + + return f, nil +} + +func parseIntHex(b []byte) (int64, error) { + cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:]) + if err != nil { + return 0, err + } + + i, err := strconv.ParseInt(string(cleaned), 16, 64) + if err != nil { + return 0, unstable.NewParserError(b, "couldn't parse hexadecimal number: %w", err) + } + + return i, nil +} + +func parseIntOct(b []byte) (int64, error) { + cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:]) + if err != nil { + return 0, err + } + + i, err := strconv.ParseInt(string(cleaned), 8, 64) + if err != nil { + return 0, unstable.NewParserError(b, "couldn't parse octal number: %w", err) + } + + return i, nil +} + +func parseIntBin(b []byte) (int64, error) { + cleaned, err := checkAndRemoveUnderscoresIntegers(b[2:]) + if err != nil { + return 0, err + } + + i, err := strconv.ParseInt(string(cleaned), 2, 64) + if err != nil { + return 0, unstable.NewParserError(b, "couldn't parse binary number: %w", err) + } + + return i, nil +} + +func isSign(b byte) bool { + return b == '+' || b == '-' +} + +func parseIntDec(b []byte) (int64, error) { + cleaned, err := checkAndRemoveUnderscoresIntegers(b) + if err != nil { + return 0, err + } + + startIdx := 0 + + if isSign(cleaned[0]) { + startIdx++ + } + + if len(cleaned) > startIdx+1 && cleaned[startIdx] == '0' { + return 0, unstable.NewParserError(b, "leading zero not allowed on decimal number") + } + + i, err := strconv.ParseInt(string(cleaned), 10, 64) + if err != nil { + return 0, unstable.NewParserError(b, "couldn't parse decimal number: %w", err) + } + + return i, nil +} + +func checkAndRemoveUnderscoresIntegers(b []byte) ([]byte, error) { + start := 0 + if b[start] == '+' || b[start] == '-' { + start++ + } + + if len(b) == start { + return b, nil + } + + if b[start] == '_' { + return nil, unstable.NewParserError(b[start:start+1], "number cannot start with underscore") + } + + if b[len(b)-1] == '_' { + return nil, unstable.NewParserError(b[len(b)-1:], "number cannot end with underscore") + } + + // fast path + i := 0 + for ; i < len(b); i++ { + if b[i] == '_' { + break + } + } + if i == len(b) { + return b, nil + } + + before := false + cleaned := make([]byte, i, len(b)) + copy(cleaned, b) + + for i++; i < len(b); i++ { + c := b[i] + if c == '_' { + if !before { + return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores") + } + before = false + } else { + before = true + cleaned = append(cleaned, c) + } + } + + return cleaned, nil +} + +func checkAndRemoveUnderscoresFloats(b []byte) ([]byte, error) { + if b[0] == '_' { + return nil, unstable.NewParserError(b[0:1], "number cannot start with underscore") + } + + if b[len(b)-1] == '_' { + return nil, unstable.NewParserError(b[len(b)-1:], "number cannot end with underscore") + } + + // fast path + i := 0 + for ; i < len(b); i++ { + if b[i] == '_' { + break + } + } + if i == len(b) { + return b, nil + } + + before := false + cleaned := make([]byte, 0, len(b)) + + for i := 0; i < len(b); i++ { + c := b[i] + + switch c { + case '_': + if !before { + return nil, unstable.NewParserError(b[i-1:i+1], "number must have at least one digit between underscores") + } + if i < len(b)-1 && (b[i+1] == 'e' || b[i+1] == 'E') { + return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore before exponent") + } + before = false + case '+', '-': + // signed exponents + cleaned = append(cleaned, c) + before = false + case 'e', 'E': + if i < len(b)-1 && b[i+1] == '_' { + return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after exponent") + } + cleaned = append(cleaned, c) + case '.': + if i < len(b)-1 && b[i+1] == '_' { + return nil, unstable.NewParserError(b[i+1:i+2], "cannot have underscore after decimal point") + } + if i > 0 && b[i-1] == '_' { + return nil, unstable.NewParserError(b[i-1:i], "cannot have underscore before decimal point") + } + cleaned = append(cleaned, c) + default: + before = true + cleaned = append(cleaned, c) + } + } + + return cleaned, nil +} + +// isValidDate checks if a provided date is a date that exists. +func isValidDate(year int, month int, day int) bool { + return month > 0 && month < 13 && day > 0 && day <= daysIn(month, year) +} + +// daysBefore[m] counts the number of days in a non-leap year +// before month m begins. There is an entry for m=12, counting +// the number of days before January of next year (365). +var daysBefore = [...]int32{ + 0, + 31, + 31 + 28, + 31 + 28 + 31, + 31 + 28 + 31 + 30, + 31 + 28 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30, + 31 + 28 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30 + 31, +} + +func daysIn(m int, year int) int { + if m == 2 && isLeap(year) { + return 29 + } + return int(daysBefore[m] - daysBefore[m-1]) +} + +func isLeap(year int) bool { + return year%4 == 0 && (year%100 != 0 || year%400 == 0) +} + +func isDigit(r byte) bool { + return r >= '0' && r <= '9' +} diff --git a/vendor/github.com/pelletier/go-toml/v2/doc.go b/vendor/github.com/pelletier/go-toml/v2/doc.go new file mode 100644 index 0000000000..b7bc599bde --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/doc.go @@ -0,0 +1,2 @@ +// Package toml is a library to read and write TOML documents. +package toml diff --git a/vendor/github.com/pelletier/go-toml/v2/errors.go b/vendor/github.com/pelletier/go-toml/v2/errors.go new file mode 100644 index 0000000000..309733f1f9 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/errors.go @@ -0,0 +1,252 @@ +package toml + +import ( + "fmt" + "strconv" + "strings" + + "github.com/pelletier/go-toml/v2/internal/danger" + "github.com/pelletier/go-toml/v2/unstable" +) + +// DecodeError represents an error encountered during the parsing or decoding +// of a TOML document. +// +// In addition to the error message, it contains the position in the document +// where it happened, as well as a human-readable representation that shows +// where the error occurred in the document. +type DecodeError struct { + message string + line int + column int + key Key + + human string +} + +// StrictMissingError occurs in a TOML document that does not have a +// corresponding field in the target value. It contains all the missing fields +// in Errors. +// +// Emitted by Decoder when DisallowUnknownFields() was called. +type StrictMissingError struct { + // One error per field that could not be found. + Errors []DecodeError +} + +// Error returns the canonical string for this error. +func (s *StrictMissingError) Error() string { + return "strict mode: fields in the document are missing in the target struct" +} + +// String returns a human readable description of all errors. +func (s *StrictMissingError) String() string { + var buf strings.Builder + + for i, e := range s.Errors { + if i > 0 { + buf.WriteString("\n---\n") + } + + buf.WriteString(e.String()) + } + + return buf.String() +} + +type Key []string + +// Error returns the error message contained in the DecodeError. +func (e *DecodeError) Error() string { + return "toml: " + e.message +} + +// String returns the human-readable contextualized error. This string is multi-line. +func (e *DecodeError) String() string { + return e.human +} + +// Position returns the (line, column) pair indicating where the error +// occurred in the document. Positions are 1-indexed. +func (e *DecodeError) Position() (row int, column int) { + return e.line, e.column +} + +// Key that was being processed when the error occurred. The key is present only +// if this DecodeError is part of a StrictMissingError. +func (e *DecodeError) Key() Key { + return e.key +} + +// decodeErrorFromHighlight creates a DecodeError referencing a highlighted +// range of bytes from document. +// +// highlight needs to be a sub-slice of document, or this function panics. +// +// The function copies all bytes used in DecodeError, so that document and +// highlight can be freely deallocated. +// +//nolint:funlen +func wrapDecodeError(document []byte, de *unstable.ParserError) *DecodeError { + offset := danger.SubsliceOffset(document, de.Highlight) + + errMessage := de.Error() + errLine, errColumn := positionAtEnd(document[:offset]) + before, after := linesOfContext(document, de.Highlight, offset, 3) + + var buf strings.Builder + + maxLine := errLine + len(after) - 1 + lineColumnWidth := len(strconv.Itoa(maxLine)) + + // Write the lines of context strictly before the error. + for i := len(before) - 1; i > 0; i-- { + line := errLine - i + buf.WriteString(formatLineNumber(line, lineColumnWidth)) + buf.WriteString("|") + + if len(before[i]) > 0 { + buf.WriteString(" ") + buf.Write(before[i]) + } + + buf.WriteRune('\n') + } + + // Write the document line that contains the error. + + buf.WriteString(formatLineNumber(errLine, lineColumnWidth)) + buf.WriteString("| ") + + if len(before) > 0 { + buf.Write(before[0]) + } + + buf.Write(de.Highlight) + + if len(after) > 0 { + buf.Write(after[0]) + } + + buf.WriteRune('\n') + + // Write the line with the error message itself (so it does not have a line + // number). + + buf.WriteString(strings.Repeat(" ", lineColumnWidth)) + buf.WriteString("| ") + + if len(before) > 0 { + buf.WriteString(strings.Repeat(" ", len(before[0]))) + } + + buf.WriteString(strings.Repeat("~", len(de.Highlight))) + + if len(errMessage) > 0 { + buf.WriteString(" ") + buf.WriteString(errMessage) + } + + // Write the lines of context strictly after the error. + + for i := 1; i < len(after); i++ { + buf.WriteRune('\n') + line := errLine + i + buf.WriteString(formatLineNumber(line, lineColumnWidth)) + buf.WriteString("|") + + if len(after[i]) > 0 { + buf.WriteString(" ") + buf.Write(after[i]) + } + } + + return &DecodeError{ + message: errMessage, + line: errLine, + column: errColumn, + key: de.Key, + human: buf.String(), + } +} + +func formatLineNumber(line int, width int) string { + format := "%" + strconv.Itoa(width) + "d" + + return fmt.Sprintf(format, line) +} + +func linesOfContext(document []byte, highlight []byte, offset int, linesAround int) ([][]byte, [][]byte) { + return beforeLines(document, offset, linesAround), afterLines(document, highlight, offset, linesAround) +} + +func beforeLines(document []byte, offset int, linesAround int) [][]byte { + var beforeLines [][]byte + + // Walk the document backward from the highlight to find previous lines + // of context. + rest := document[:offset] +backward: + for o := len(rest) - 1; o >= 0 && len(beforeLines) <= linesAround && len(rest) > 0; { + switch { + case rest[o] == '\n': + // handle individual lines + beforeLines = append(beforeLines, rest[o+1:]) + rest = rest[:o] + o = len(rest) - 1 + case o == 0: + // add the first line only if it's non-empty + beforeLines = append(beforeLines, rest) + + break backward + default: + o-- + } + } + + return beforeLines +} + +func afterLines(document []byte, highlight []byte, offset int, linesAround int) [][]byte { + var afterLines [][]byte + + // Walk the document forward from the highlight to find the following + // lines of context. + rest := document[offset+len(highlight):] +forward: + for o := 0; o < len(rest) && len(afterLines) <= linesAround; { + switch { + case rest[o] == '\n': + // handle individual lines + afterLines = append(afterLines, rest[:o]) + rest = rest[o+1:] + o = 0 + + case o == len(rest)-1: + // add last line only if it's non-empty + afterLines = append(afterLines, rest) + + break forward + default: + o++ + } + } + + return afterLines +} + +func positionAtEnd(b []byte) (row int, column int) { + row = 1 + column = 1 + + for _, c := range b { + if c == '\n' { + row++ + column = 1 + } else { + column++ + } + } + + return +} diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go b/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go new file mode 100644 index 0000000000..80f698db4b --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/characters/ascii.go @@ -0,0 +1,42 @@ +package characters + +var invalidAsciiTable = [256]bool{ + 0x00: true, + 0x01: true, + 0x02: true, + 0x03: true, + 0x04: true, + 0x05: true, + 0x06: true, + 0x07: true, + 0x08: true, + // 0x09 TAB + // 0x0A LF + 0x0B: true, + 0x0C: true, + // 0x0D CR + 0x0E: true, + 0x0F: true, + 0x10: true, + 0x11: true, + 0x12: true, + 0x13: true, + 0x14: true, + 0x15: true, + 0x16: true, + 0x17: true, + 0x18: true, + 0x19: true, + 0x1A: true, + 0x1B: true, + 0x1C: true, + 0x1D: true, + 0x1E: true, + 0x1F: true, + // 0x20 - 0x7E Printable ASCII characters + 0x7F: true, +} + +func InvalidAscii(b byte) bool { + return invalidAsciiTable[b] +} diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go b/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go new file mode 100644 index 0000000000..db4f45acbf --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/characters/utf8.go @@ -0,0 +1,199 @@ +package characters + +import ( + "unicode/utf8" +) + +type utf8Err struct { + Index int + Size int +} + +func (u utf8Err) Zero() bool { + return u.Size == 0 +} + +// Verified that a given string is only made of valid UTF-8 characters allowed +// by the TOML spec: +// +// Any Unicode character may be used except those that must be escaped: +// quotation mark, backslash, and the control characters other than tab (U+0000 +// to U+0008, U+000A to U+001F, U+007F). +// +// It is a copy of the Go 1.17 utf8.Valid implementation, tweaked to exit early +// when a character is not allowed. +// +// The returned utf8Err is Zero() if the string is valid, or contains the byte +// index and size of the invalid character. +// +// quotation mark => already checked +// backslash => already checked +// 0-0x8 => invalid +// 0x9 => tab, ok +// 0xA - 0x1F => invalid +// 0x7F => invalid +func Utf8TomlValidAlreadyEscaped(p []byte) (err utf8Err) { + // Fast path. Check for and skip 8 bytes of ASCII characters per iteration. + offset := 0 + for len(p) >= 8 { + // Combining two 32 bit loads allows the same code to be used + // for 32 and 64 bit platforms. + // The compiler can generate a 32bit load for first32 and second32 + // on many platforms. See test/codegen/memcombine.go. + first32 := uint32(p[0]) | uint32(p[1])<<8 | uint32(p[2])<<16 | uint32(p[3])<<24 + second32 := uint32(p[4]) | uint32(p[5])<<8 | uint32(p[6])<<16 | uint32(p[7])<<24 + if (first32|second32)&0x80808080 != 0 { + // Found a non ASCII byte (>= RuneSelf). + break + } + + for i, b := range p[:8] { + if InvalidAscii(b) { + err.Index = offset + i + err.Size = 1 + return + } + } + + p = p[8:] + offset += 8 + } + n := len(p) + for i := 0; i < n; { + pi := p[i] + if pi < utf8.RuneSelf { + if InvalidAscii(pi) { + err.Index = offset + i + err.Size = 1 + return + } + i++ + continue + } + x := first[pi] + if x == xx { + // Illegal starter byte. + err.Index = offset + i + err.Size = 1 + return + } + size := int(x & 7) + if i+size > n { + // Short or invalid. + err.Index = offset + i + err.Size = n - i + return + } + accept := acceptRanges[x>>4] + if c := p[i+1]; c < accept.lo || accept.hi < c { + err.Index = offset + i + err.Size = 2 + return + } else if size == 2 { + } else if c := p[i+2]; c < locb || hicb < c { + err.Index = offset + i + err.Size = 3 + return + } else if size == 3 { + } else if c := p[i+3]; c < locb || hicb < c { + err.Index = offset + i + err.Size = 4 + return + } + i += size + } + return +} + +// Return the size of the next rune if valid, 0 otherwise. +func Utf8ValidNext(p []byte) int { + c := p[0] + + if c < utf8.RuneSelf { + if InvalidAscii(c) { + return 0 + } + return 1 + } + + x := first[c] + if x == xx { + // Illegal starter byte. + return 0 + } + size := int(x & 7) + if size > len(p) { + // Short or invalid. + return 0 + } + accept := acceptRanges[x>>4] + if c := p[1]; c < accept.lo || accept.hi < c { + return 0 + } else if size == 2 { + } else if c := p[2]; c < locb || hicb < c { + return 0 + } else if size == 3 { + } else if c := p[3]; c < locb || hicb < c { + return 0 + } + + return size +} + +// acceptRange gives the range of valid values for the second byte in a UTF-8 +// sequence. +type acceptRange struct { + lo uint8 // lowest value for second byte. + hi uint8 // highest value for second byte. +} + +// acceptRanges has size 16 to avoid bounds checks in the code that uses it. +var acceptRanges = [16]acceptRange{ + 0: {locb, hicb}, + 1: {0xA0, hicb}, + 2: {locb, 0x9F}, + 3: {0x90, hicb}, + 4: {locb, 0x8F}, +} + +// first is information about the first byte in a UTF-8 sequence. +var first = [256]uint8{ + // 1 2 3 4 5 6 7 8 9 A B C D E F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x00-0x0F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x10-0x1F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x20-0x2F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x30-0x3F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x40-0x4F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x50-0x5F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x60-0x6F + as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, as, // 0x70-0x7F + // 1 2 3 4 5 6 7 8 9 A B C D E F + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x80-0x8F + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0x90-0x9F + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xA0-0xAF + xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xB0-0xBF + xx, xx, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xC0-0xCF + s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, s1, // 0xD0-0xDF + s2, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s3, s4, s3, s3, // 0xE0-0xEF + s5, s6, s6, s6, s7, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, xx, // 0xF0-0xFF +} + +const ( + // The default lowest and highest continuation byte. + locb = 0b10000000 + hicb = 0b10111111 + + // These names of these constants are chosen to give nice alignment in the + // table below. The first nibble is an index into acceptRanges or F for + // special one-byte cases. The second nibble is the Rune length or the + // Status for the special one-byte case. + xx = 0xF1 // invalid: size 1 + as = 0xF0 // ASCII: size 1 + s1 = 0x02 // accept 0, size 2 + s2 = 0x13 // accept 1, size 3 + s3 = 0x03 // accept 0, size 3 + s4 = 0x23 // accept 2, size 3 + s5 = 0x34 // accept 3, size 4 + s6 = 0x04 // accept 0, size 4 + s7 = 0x44 // accept 4, size 4 +) diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go b/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go new file mode 100644 index 0000000000..e38e1131b8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/danger/danger.go @@ -0,0 +1,65 @@ +package danger + +import ( + "fmt" + "reflect" + "unsafe" +) + +const maxInt = uintptr(int(^uint(0) >> 1)) + +func SubsliceOffset(data []byte, subslice []byte) int { + datap := (*reflect.SliceHeader)(unsafe.Pointer(&data)) + hlp := (*reflect.SliceHeader)(unsafe.Pointer(&subslice)) + + if hlp.Data < datap.Data { + panic(fmt.Errorf("subslice address (%d) is before data address (%d)", hlp.Data, datap.Data)) + } + offset := hlp.Data - datap.Data + + if offset > maxInt { + panic(fmt.Errorf("slice offset larger than int (%d)", offset)) + } + + intoffset := int(offset) + + if intoffset > datap.Len { + panic(fmt.Errorf("slice offset (%d) is farther than data length (%d)", intoffset, datap.Len)) + } + + if intoffset+hlp.Len > datap.Len { + panic(fmt.Errorf("slice ends (%d+%d) is farther than data length (%d)", intoffset, hlp.Len, datap.Len)) + } + + return intoffset +} + +func BytesRange(start []byte, end []byte) []byte { + if start == nil || end == nil { + panic("cannot call BytesRange with nil") + } + startp := (*reflect.SliceHeader)(unsafe.Pointer(&start)) + endp := (*reflect.SliceHeader)(unsafe.Pointer(&end)) + + if startp.Data > endp.Data { + panic(fmt.Errorf("start pointer address (%d) is after end pointer address (%d)", startp.Data, endp.Data)) + } + + l := startp.Len + endLen := int(endp.Data-startp.Data) + endp.Len + if endLen > l { + l = endLen + } + + if l > startp.Cap { + panic(fmt.Errorf("range length is larger than capacity")) + } + + return start[:l] +} + +func Stride(ptr unsafe.Pointer, size uintptr, offset int) unsafe.Pointer { + // TODO: replace with unsafe.Add when Go 1.17 is released + // https://github.com/golang/go/issues/40481 + return unsafe.Pointer(uintptr(ptr) + uintptr(int(size)*offset)) +} diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go b/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go new file mode 100644 index 0000000000..9d41c28a2f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/danger/typeid.go @@ -0,0 +1,23 @@ +package danger + +import ( + "reflect" + "unsafe" +) + +// typeID is used as key in encoder and decoder caches to enable using +// the optimize runtime.mapaccess2_fast64 function instead of the more +// expensive lookup if we were to use reflect.Type as map key. +// +// typeID holds the pointer to the reflect.Type value, which is unique +// in the program. +// +// https://github.com/segmentio/encoding/blob/master/json/codec.go#L59-L61 +type TypeID unsafe.Pointer + +func MakeTypeID(t reflect.Type) TypeID { + // reflect.Type has the fields: + // typ unsafe.Pointer + // ptr unsafe.Pointer + return TypeID((*[2]unsafe.Pointer)(unsafe.Pointer(&t))[1]) +} diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go new file mode 100644 index 0000000000..149b17f538 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/key.go @@ -0,0 +1,48 @@ +package tracker + +import "github.com/pelletier/go-toml/v2/unstable" + +// KeyTracker is a tracker that keeps track of the current Key as the AST is +// walked. +type KeyTracker struct { + k []string +} + +// UpdateTable sets the state of the tracker with the AST table node. +func (t *KeyTracker) UpdateTable(node *unstable.Node) { + t.reset() + t.Push(node) +} + +// UpdateArrayTable sets the state of the tracker with the AST array table node. +func (t *KeyTracker) UpdateArrayTable(node *unstable.Node) { + t.reset() + t.Push(node) +} + +// Push the given key on the stack. +func (t *KeyTracker) Push(node *unstable.Node) { + it := node.Key() + for it.Next() { + t.k = append(t.k, string(it.Node().Data)) + } +} + +// Pop key from stack. +func (t *KeyTracker) Pop(node *unstable.Node) { + it := node.Key() + for it.Next() { + t.k = t.k[:len(t.k)-1] + } +} + +// Key returns the current key +func (t *KeyTracker) Key() []string { + k := make([]string, len(t.k)) + copy(k, t.k) + return k +} + +func (t *KeyTracker) reset() { + t.k = t.k[:0] +} diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go new file mode 100644 index 0000000000..76df2d5b6a --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/seen.go @@ -0,0 +1,358 @@ +package tracker + +import ( + "bytes" + "fmt" + "sync" + + "github.com/pelletier/go-toml/v2/unstable" +) + +type keyKind uint8 + +const ( + invalidKind keyKind = iota + valueKind + tableKind + arrayTableKind +) + +func (k keyKind) String() string { + switch k { + case invalidKind: + return "invalid" + case valueKind: + return "value" + case tableKind: + return "table" + case arrayTableKind: + return "array table" + } + panic("missing keyKind string mapping") +} + +// SeenTracker tracks which keys have been seen with which TOML type to flag +// duplicates and mismatches according to the spec. +// +// Each node in the visited tree is represented by an entry. Each entry has an +// identifier, which is provided by a counter. Entries are stored in the array +// entries. As new nodes are discovered (referenced for the first time in the +// TOML document), entries are created and appended to the array. An entry +// points to its parent using its id. +// +// To find whether a given key (sequence of []byte) has already been visited, +// the entries are linearly searched, looking for one with the right name and +// parent id. +// +// Given that all keys appear in the document after their parent, it is +// guaranteed that all descendants of a node are stored after the node, this +// speeds up the search process. +// +// When encountering [[array tables]], the descendants of that node are removed +// to allow that branch of the tree to be "rediscovered". To maintain the +// invariant above, the deletion process needs to keep the order of entries. +// This results in more copies in that case. +type SeenTracker struct { + entries []entry + currentIdx int +} + +var pool = sync.Pool{ + New: func() interface{} { + return &SeenTracker{} + }, +} + +func (s *SeenTracker) reset() { + // Always contains a root element at index 0. + s.currentIdx = 0 + if len(s.entries) == 0 { + s.entries = make([]entry, 1, 2) + } else { + s.entries = s.entries[:1] + } + s.entries[0].child = -1 + s.entries[0].next = -1 +} + +type entry struct { + // Use -1 to indicate no child or no sibling. + child int + next int + + name []byte + kind keyKind + explicit bool + kv bool +} + +// Find the index of the child of parentIdx with key k. Returns -1 if +// it does not exist. +func (s *SeenTracker) find(parentIdx int, k []byte) int { + for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next { + if bytes.Equal(s.entries[i].name, k) { + return i + } + } + return -1 +} + +// Remove all descendants of node at position idx. +func (s *SeenTracker) clear(idx int) { + if idx >= len(s.entries) { + return + } + + for i := s.entries[idx].child; i >= 0; { + next := s.entries[i].next + n := s.entries[0].next + s.entries[0].next = i + s.entries[i].next = n + s.entries[i].name = nil + s.clear(i) + i = next + } + + s.entries[idx].child = -1 +} + +func (s *SeenTracker) create(parentIdx int, name []byte, kind keyKind, explicit bool, kv bool) int { + e := entry{ + child: -1, + next: s.entries[parentIdx].child, + + name: name, + kind: kind, + explicit: explicit, + kv: kv, + } + var idx int + if s.entries[0].next >= 0 { + idx = s.entries[0].next + s.entries[0].next = s.entries[idx].next + s.entries[idx] = e + } else { + idx = len(s.entries) + s.entries = append(s.entries, e) + } + + s.entries[parentIdx].child = idx + + return idx +} + +func (s *SeenTracker) setExplicitFlag(parentIdx int) { + for i := s.entries[parentIdx].child; i >= 0; i = s.entries[i].next { + if s.entries[i].kv { + s.entries[i].explicit = true + s.entries[i].kv = false + } + s.setExplicitFlag(i) + } +} + +// CheckExpression takes a top-level node and checks that it does not contain +// keys that have been seen in previous calls, and validates that types are +// consistent. It returns true if it is the first time this node's key is seen. +// Useful to clear array tables on first use. +func (s *SeenTracker) CheckExpression(node *unstable.Node) (bool, error) { + if s.entries == nil { + s.reset() + } + switch node.Kind { + case unstable.KeyValue: + return s.checkKeyValue(node) + case unstable.Table: + return s.checkTable(node) + case unstable.ArrayTable: + return s.checkArrayTable(node) + default: + panic(fmt.Errorf("this should not be a top level node type: %s", node.Kind)) + } +} + +func (s *SeenTracker) checkTable(node *unstable.Node) (bool, error) { + if s.currentIdx >= 0 { + s.setExplicitFlag(s.currentIdx) + } + + it := node.Key() + + parentIdx := 0 + + // This code is duplicated in checkArrayTable. This is because factoring + // it in a function requires to copy the iterator, or allocate it to the + // heap, which is not cheap. + for it.Next() { + if it.IsLast() { + break + } + + k := it.Node().Data + + idx := s.find(parentIdx, k) + + if idx < 0 { + idx = s.create(parentIdx, k, tableKind, false, false) + } else { + entry := s.entries[idx] + if entry.kind == valueKind { + return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind) + } + } + parentIdx = idx + } + + k := it.Node().Data + idx := s.find(parentIdx, k) + + first := false + if idx >= 0 { + kind := s.entries[idx].kind + if kind != tableKind { + return false, fmt.Errorf("toml: key %s should be a table, not a %s", string(k), kind) + } + if s.entries[idx].explicit { + return false, fmt.Errorf("toml: table %s already exists", string(k)) + } + s.entries[idx].explicit = true + } else { + idx = s.create(parentIdx, k, tableKind, true, false) + first = true + } + + s.currentIdx = idx + + return first, nil +} + +func (s *SeenTracker) checkArrayTable(node *unstable.Node) (bool, error) { + if s.currentIdx >= 0 { + s.setExplicitFlag(s.currentIdx) + } + + it := node.Key() + + parentIdx := 0 + + for it.Next() { + if it.IsLast() { + break + } + + k := it.Node().Data + + idx := s.find(parentIdx, k) + + if idx < 0 { + idx = s.create(parentIdx, k, tableKind, false, false) + } else { + entry := s.entries[idx] + if entry.kind == valueKind { + return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind) + } + } + + parentIdx = idx + } + + k := it.Node().Data + idx := s.find(parentIdx, k) + + firstTime := idx < 0 + if firstTime { + idx = s.create(parentIdx, k, arrayTableKind, true, false) + } else { + kind := s.entries[idx].kind + if kind != arrayTableKind { + return false, fmt.Errorf("toml: key %s already exists as a %s, but should be an array table", kind, string(k)) + } + s.clear(idx) + } + + s.currentIdx = idx + + return firstTime, nil +} + +func (s *SeenTracker) checkKeyValue(node *unstable.Node) (bool, error) { + parentIdx := s.currentIdx + it := node.Key() + + for it.Next() { + k := it.Node().Data + + idx := s.find(parentIdx, k) + + if idx < 0 { + idx = s.create(parentIdx, k, tableKind, false, true) + } else { + entry := s.entries[idx] + if it.IsLast() { + return false, fmt.Errorf("toml: key %s is already defined", string(k)) + } else if entry.kind != tableKind { + return false, fmt.Errorf("toml: expected %s to be a table, not a %s", string(k), entry.kind) + } else if entry.explicit { + return false, fmt.Errorf("toml: cannot redefine table %s that has already been explicitly defined", string(k)) + } + } + + parentIdx = idx + } + + s.entries[parentIdx].kind = valueKind + + value := node.Value() + + switch value.Kind { + case unstable.InlineTable: + return s.checkInlineTable(value) + case unstable.Array: + return s.checkArray(value) + } + + return false, nil +} + +func (s *SeenTracker) checkArray(node *unstable.Node) (first bool, err error) { + it := node.Children() + for it.Next() { + n := it.Node() + switch n.Kind { + case unstable.InlineTable: + first, err = s.checkInlineTable(n) + if err != nil { + return false, err + } + case unstable.Array: + first, err = s.checkArray(n) + if err != nil { + return false, err + } + } + } + return first, nil +} + +func (s *SeenTracker) checkInlineTable(node *unstable.Node) (first bool, err error) { + s = pool.Get().(*SeenTracker) + s.reset() + + it := node.Children() + for it.Next() { + n := it.Node() + first, err = s.checkKeyValue(n) + if err != nil { + return false, err + } + } + + // As inline tables are self-contained, the tracker does not + // need to retain the details of what they contain. The + // keyValue element that creates the inline table is kept to + // mark the presence of the inline table and prevent + // redefinition of its keys: check* functions cannot walk into + // a value. + pool.Put(s) + return first, nil +} diff --git a/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go new file mode 100644 index 0000000000..bf0317392f --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/internal/tracker/tracker.go @@ -0,0 +1 @@ +package tracker diff --git a/vendor/github.com/pelletier/go-toml/v2/localtime.go b/vendor/github.com/pelletier/go-toml/v2/localtime.go new file mode 100644 index 0000000000..a856bfdb0d --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/localtime.go @@ -0,0 +1,122 @@ +package toml + +import ( + "fmt" + "strings" + "time" + + "github.com/pelletier/go-toml/v2/unstable" +) + +// LocalDate represents a calendar day in no specific timezone. +type LocalDate struct { + Year int + Month int + Day int +} + +// AsTime converts d into a specific time instance at midnight in zone. +func (d LocalDate) AsTime(zone *time.Location) time.Time { + return time.Date(d.Year, time.Month(d.Month), d.Day, 0, 0, 0, 0, zone) +} + +// String returns RFC 3339 representation of d. +func (d LocalDate) String() string { + return fmt.Sprintf("%04d-%02d-%02d", d.Year, d.Month, d.Day) +} + +// MarshalText returns RFC 3339 representation of d. +func (d LocalDate) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// UnmarshalText parses b using RFC 3339 to fill d. +func (d *LocalDate) UnmarshalText(b []byte) error { + res, err := parseLocalDate(b) + if err != nil { + return err + } + *d = res + return nil +} + +// LocalTime represents a time of day of no specific day in no specific +// timezone. +type LocalTime struct { + Hour int // Hour of the day: [0; 24[ + Minute int // Minute of the hour: [0; 60[ + Second int // Second of the minute: [0; 60[ + Nanosecond int // Nanoseconds within the second: [0, 1000000000[ + Precision int // Number of digits to display for Nanosecond. +} + +// String returns RFC 3339 representation of d. +// If d.Nanosecond and d.Precision are zero, the time won't have a nanosecond +// component. If d.Nanosecond > 0 but d.Precision = 0, then the minimum number +// of digits for nanoseconds is provided. +func (d LocalTime) String() string { + s := fmt.Sprintf("%02d:%02d:%02d", d.Hour, d.Minute, d.Second) + + if d.Precision > 0 { + s += fmt.Sprintf(".%09d", d.Nanosecond)[:d.Precision+1] + } else if d.Nanosecond > 0 { + // Nanoseconds are specified, but precision is not provided. Use the + // minimum. + s += strings.Trim(fmt.Sprintf(".%09d", d.Nanosecond), "0") + } + + return s +} + +// MarshalText returns RFC 3339 representation of d. +func (d LocalTime) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// UnmarshalText parses b using RFC 3339 to fill d. +func (d *LocalTime) UnmarshalText(b []byte) error { + res, left, err := parseLocalTime(b) + if err == nil && len(left) != 0 { + err = unstable.NewParserError(left, "extra characters") + } + if err != nil { + return err + } + *d = res + return nil +} + +// LocalDateTime represents a time of a specific day in no specific timezone. +type LocalDateTime struct { + LocalDate + LocalTime +} + +// AsTime converts d into a specific time instance in zone. +func (d LocalDateTime) AsTime(zone *time.Location) time.Time { + return time.Date(d.Year, time.Month(d.Month), d.Day, d.Hour, d.Minute, d.Second, d.Nanosecond, zone) +} + +// String returns RFC 3339 representation of d. +func (d LocalDateTime) String() string { + return d.LocalDate.String() + "T" + d.LocalTime.String() +} + +// MarshalText returns RFC 3339 representation of d. +func (d LocalDateTime) MarshalText() ([]byte, error) { + return []byte(d.String()), nil +} + +// UnmarshalText parses b using RFC 3339 to fill d. +func (d *LocalDateTime) UnmarshalText(data []byte) error { + res, left, err := parseLocalDateTime(data) + if err == nil && len(left) != 0 { + err = unstable.NewParserError(left, "extra characters") + } + if err != nil { + return err + } + + *d = res + return nil +} diff --git a/vendor/github.com/pelletier/go-toml/v2/marshaler.go b/vendor/github.com/pelletier/go-toml/v2/marshaler.go new file mode 100644 index 0000000000..161acd9343 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/marshaler.go @@ -0,0 +1,1133 @@ +package toml + +import ( + "bytes" + "encoding" + "encoding/json" + "fmt" + "io" + "math" + "reflect" + "slices" + "strconv" + "strings" + "time" + "unicode" + + "github.com/pelletier/go-toml/v2/internal/characters" +) + +// Marshal serializes a Go value as a TOML document. +// +// It is a shortcut for Encoder.Encode() with the default options. +func Marshal(v interface{}) ([]byte, error) { + var buf bytes.Buffer + enc := NewEncoder(&buf) + + err := enc.Encode(v) + if err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +// Encoder writes a TOML document to an output stream. +type Encoder struct { + // output + w io.Writer + + // global settings + tablesInline bool + arraysMultiline bool + indentSymbol string + indentTables bool + marshalJsonNumbers bool +} + +// NewEncoder returns a new Encoder that writes to w. +func NewEncoder(w io.Writer) *Encoder { + return &Encoder{ + w: w, + indentSymbol: " ", + } +} + +// SetTablesInline forces the encoder to emit all tables inline. +// +// This behavior can be controlled on an individual struct field basis with the +// inline tag: +// +// MyField `toml:",inline"` +func (enc *Encoder) SetTablesInline(inline bool) *Encoder { + enc.tablesInline = inline + return enc +} + +// SetArraysMultiline forces the encoder to emit all arrays with one element per +// line. +// +// This behavior can be controlled on an individual struct field basis with the multiline tag: +// +// MyField `multiline:"true"` +func (enc *Encoder) SetArraysMultiline(multiline bool) *Encoder { + enc.arraysMultiline = multiline + return enc +} + +// SetIndentSymbol defines the string that should be used for indentation. The +// provided string is repeated for each indentation level. Defaults to two +// spaces. +func (enc *Encoder) SetIndentSymbol(s string) *Encoder { + enc.indentSymbol = s + return enc +} + +// SetIndentTables forces the encoder to intent tables and array tables. +func (enc *Encoder) SetIndentTables(indent bool) *Encoder { + enc.indentTables = indent + return enc +} + +// SetMarshalJsonNumbers forces the encoder to serialize `json.Number` as a +// float or integer instead of relying on TextMarshaler to emit a string. +// +// *Unstable:* This method does not follow the compatibility guarantees of +// semver. It can be changed or removed without a new major version being +// issued. +func (enc *Encoder) SetMarshalJsonNumbers(indent bool) *Encoder { + enc.marshalJsonNumbers = indent + return enc +} + +// Encode writes a TOML representation of v to the stream. +// +// If v cannot be represented to TOML it returns an error. +// +// # Encoding rules +// +// A top level slice containing only maps or structs is encoded as [[table +// array]]. +// +// All slices not matching rule 1 are encoded as [array]. As a result, any map +// or struct they contain is encoded as an {inline table}. +// +// Nil interfaces and nil pointers are not supported. +// +// Keys in key-values always have one part. +// +// Intermediate tables are always printed. +// +// By default, strings are encoded as literal string, unless they contain either +// a newline character or a single quote. In that case they are emitted as +// quoted strings. +// +// Unsigned integers larger than math.MaxInt64 cannot be encoded. Doing so +// results in an error. This rule exists because the TOML specification only +// requires parsers to support at least the 64 bits integer range. Allowing +// larger numbers would create non-standard TOML documents, which may not be +// readable (at best) by other implementations. To encode such numbers, a +// solution is a custom type that implements encoding.TextMarshaler. +// +// When encoding structs, fields are encoded in order of definition, with their +// exact name. +// +// Tables and array tables are separated by empty lines. However, consecutive +// subtables definitions are not. For example: +// +// [top1] +// +// [top2] +// [top2.child1] +// +// [[array]] +// +// [[array]] +// [array.child2] +// +// # Struct tags +// +// The encoding of each public struct field can be customized by the format +// string in the "toml" key of the struct field's tag. This follows +// encoding/json's convention. The format string starts with the name of the +// field, optionally followed by a comma-separated list of options. The name may +// be empty in order to provide options without overriding the default name. +// +// The "multiline" option emits strings as quoted multi-line TOML strings. It +// has no effect on fields that would not be encoded as strings. +// +// The "inline" option turns fields that would be emitted as tables into inline +// tables instead. It has no effect on other fields. +// +// The "omitempty" option prevents empty values or groups from being emitted. +// +// The "commented" option prefixes the value and all its children with a comment +// symbol. +// +// In addition to the "toml" tag struct tag, a "comment" tag can be used to emit +// a TOML comment before the value being annotated. Comments are ignored inside +// inline tables. For array tables, the comment is only present before the first +// element of the array. +func (enc *Encoder) Encode(v interface{}) error { + var ( + b []byte + ctx encoderCtx + ) + + ctx.inline = enc.tablesInline + + if v == nil { + return fmt.Errorf("toml: cannot encode a nil interface") + } + + b, err := enc.encode(b, ctx, reflect.ValueOf(v)) + if err != nil { + return err + } + + _, err = enc.w.Write(b) + if err != nil { + return fmt.Errorf("toml: cannot write: %w", err) + } + + return nil +} + +type valueOptions struct { + multiline bool + omitempty bool + commented bool + comment string +} + +type encoderCtx struct { + // Current top-level key. + parentKey []string + + // Key that should be used for a KV. + key string + // Extra flag to account for the empty string + hasKey bool + + // Set to true to indicate that the encoder is inside a KV, so that all + // tables need to be inlined. + insideKv bool + + // Set to true to skip the first table header in an array table. + skipTableHeader bool + + // Should the next table be encoded as inline + inline bool + + // Indentation level + indent int + + // Prefix the current value with a comment. + commented bool + + // Options coming from struct tags + options valueOptions +} + +func (ctx *encoderCtx) shiftKey() { + if ctx.hasKey { + ctx.parentKey = append(ctx.parentKey, ctx.key) + ctx.clearKey() + } +} + +func (ctx *encoderCtx) setKey(k string) { + ctx.key = k + ctx.hasKey = true +} + +func (ctx *encoderCtx) clearKey() { + ctx.key = "" + ctx.hasKey = false +} + +func (ctx *encoderCtx) isRoot() bool { + return len(ctx.parentKey) == 0 && !ctx.hasKey +} + +func (enc *Encoder) encode(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) { + i := v.Interface() + + switch x := i.(type) { + case time.Time: + if x.Nanosecond() > 0 { + return x.AppendFormat(b, time.RFC3339Nano), nil + } + return x.AppendFormat(b, time.RFC3339), nil + case LocalTime: + return append(b, x.String()...), nil + case LocalDate: + return append(b, x.String()...), nil + case LocalDateTime: + return append(b, x.String()...), nil + case json.Number: + if enc.marshalJsonNumbers { + if x == "" { /// Useful zero value. + return append(b, "0"...), nil + } else if v, err := x.Int64(); err == nil { + return enc.encode(b, ctx, reflect.ValueOf(v)) + } else if f, err := x.Float64(); err == nil { + return enc.encode(b, ctx, reflect.ValueOf(f)) + } else { + return nil, fmt.Errorf("toml: unable to convert %q to int64 or float64", x) + } + } + } + + hasTextMarshaler := v.Type().Implements(textMarshalerType) + if hasTextMarshaler || (v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) { + if !hasTextMarshaler { + v = v.Addr() + } + + if ctx.isRoot() { + return nil, fmt.Errorf("toml: type %s implementing the TextMarshaler interface cannot be a root element", v.Type()) + } + + text, err := v.Interface().(encoding.TextMarshaler).MarshalText() + if err != nil { + return nil, err + } + + b = enc.encodeString(b, string(text), ctx.options) + + return b, nil + } + + switch v.Kind() { + // containers + case reflect.Map: + return enc.encodeMap(b, ctx, v) + case reflect.Struct: + return enc.encodeStruct(b, ctx, v) + case reflect.Slice, reflect.Array: + return enc.encodeSlice(b, ctx, v) + case reflect.Interface: + if v.IsNil() { + return nil, fmt.Errorf("toml: encoding a nil interface is not supported") + } + + return enc.encode(b, ctx, v.Elem()) + case reflect.Ptr: + if v.IsNil() { + return enc.encode(b, ctx, reflect.Zero(v.Type().Elem())) + } + + return enc.encode(b, ctx, v.Elem()) + + // values + case reflect.String: + b = enc.encodeString(b, v.String(), ctx.options) + case reflect.Float32: + f := v.Float() + + if math.IsNaN(f) { + b = append(b, "nan"...) + } else if f > math.MaxFloat32 { + b = append(b, "inf"...) + } else if f < -math.MaxFloat32 { + b = append(b, "-inf"...) + } else if math.Trunc(f) == f { + b = strconv.AppendFloat(b, f, 'f', 1, 32) + } else { + b = strconv.AppendFloat(b, f, 'f', -1, 32) + } + case reflect.Float64: + f := v.Float() + if math.IsNaN(f) { + b = append(b, "nan"...) + } else if f > math.MaxFloat64 { + b = append(b, "inf"...) + } else if f < -math.MaxFloat64 { + b = append(b, "-inf"...) + } else if math.Trunc(f) == f { + b = strconv.AppendFloat(b, f, 'f', 1, 64) + } else { + b = strconv.AppendFloat(b, f, 'f', -1, 64) + } + case reflect.Bool: + if v.Bool() { + b = append(b, "true"...) + } else { + b = append(b, "false"...) + } + case reflect.Uint64, reflect.Uint32, reflect.Uint16, reflect.Uint8, reflect.Uint: + x := v.Uint() + if x > uint64(math.MaxInt64) { + return nil, fmt.Errorf("toml: not encoding uint (%d) greater than max int64 (%d)", x, int64(math.MaxInt64)) + } + b = strconv.AppendUint(b, x, 10) + case reflect.Int64, reflect.Int32, reflect.Int16, reflect.Int8, reflect.Int: + b = strconv.AppendInt(b, v.Int(), 10) + default: + return nil, fmt.Errorf("toml: cannot encode value of type %s", v.Kind()) + } + + return b, nil +} + +func isNil(v reflect.Value) bool { + switch v.Kind() { + case reflect.Ptr, reflect.Interface, reflect.Map: + return v.IsNil() + default: + return false + } +} + +func shouldOmitEmpty(options valueOptions, v reflect.Value) bool { + return options.omitempty && isEmptyValue(v) +} + +func (enc *Encoder) encodeKv(b []byte, ctx encoderCtx, options valueOptions, v reflect.Value) ([]byte, error) { + var err error + + if !ctx.inline { + b = enc.encodeComment(ctx.indent, options.comment, b) + b = enc.commented(ctx.commented, b) + b = enc.indent(ctx.indent, b) + } + + b = enc.encodeKey(b, ctx.key) + b = append(b, " = "...) + + // create a copy of the context because the value of a KV shouldn't + // modify the global context. + subctx := ctx + subctx.insideKv = true + subctx.shiftKey() + subctx.options = options + + b, err = enc.encode(b, subctx, v) + if err != nil { + return nil, err + } + + return b, nil +} + +func (enc *Encoder) commented(commented bool, b []byte) []byte { + if commented { + return append(b, "# "...) + } + return b +} + +func isEmptyValue(v reflect.Value) bool { + switch v.Kind() { + case reflect.Struct: + return isEmptyStruct(v) + case reflect.Array, reflect.Map, reflect.Slice, reflect.String: + return v.Len() == 0 + case reflect.Bool: + return !v.Bool() + case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: + return v.Int() == 0 + case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr: + return v.Uint() == 0 + case reflect.Float32, reflect.Float64: + return v.Float() == 0 + case reflect.Interface, reflect.Ptr: + return v.IsNil() + } + return false +} + +func isEmptyStruct(v reflect.Value) bool { + // TODO: merge with walkStruct and cache. + typ := v.Type() + for i := 0; i < typ.NumField(); i++ { + fieldType := typ.Field(i) + + // only consider exported fields + if fieldType.PkgPath != "" { + continue + } + + tag := fieldType.Tag.Get("toml") + + // special field name to skip field + if tag == "-" { + continue + } + + f := v.Field(i) + + if !isEmptyValue(f) { + return false + } + } + + return true +} + +const literalQuote = '\'' + +func (enc *Encoder) encodeString(b []byte, v string, options valueOptions) []byte { + if needsQuoting(v) { + return enc.encodeQuotedString(options.multiline, b, v) + } + + return enc.encodeLiteralString(b, v) +} + +func needsQuoting(v string) bool { + // TODO: vectorize + for _, b := range []byte(v) { + if b == '\'' || b == '\r' || b == '\n' || characters.InvalidAscii(b) { + return true + } + } + return false +} + +// caller should have checked that the string does not contain new lines or ' . +func (enc *Encoder) encodeLiteralString(b []byte, v string) []byte { + b = append(b, literalQuote) + b = append(b, v...) + b = append(b, literalQuote) + + return b +} + +func (enc *Encoder) encodeQuotedString(multiline bool, b []byte, v string) []byte { + stringQuote := `"` + + if multiline { + stringQuote = `"""` + } + + b = append(b, stringQuote...) + if multiline { + b = append(b, '\n') + } + + const ( + hextable = "0123456789ABCDEF" + // U+0000 to U+0008, U+000A to U+001F, U+007F + nul = 0x0 + bs = 0x8 + lf = 0xa + us = 0x1f + del = 0x7f + ) + + for _, r := range []byte(v) { + switch r { + case '\\': + b = append(b, `\\`...) + case '"': + b = append(b, `\"`...) + case '\b': + b = append(b, `\b`...) + case '\f': + b = append(b, `\f`...) + case '\n': + if multiline { + b = append(b, r) + } else { + b = append(b, `\n`...) + } + case '\r': + b = append(b, `\r`...) + case '\t': + b = append(b, `\t`...) + default: + switch { + case r >= nul && r <= bs, r >= lf && r <= us, r == del: + b = append(b, `\u00`...) + b = append(b, hextable[r>>4]) + b = append(b, hextable[r&0x0f]) + default: + b = append(b, r) + } + } + } + + b = append(b, stringQuote...) + + return b +} + +// caller should have checked that the string is in A-Z / a-z / 0-9 / - / _ . +func (enc *Encoder) encodeUnquotedKey(b []byte, v string) []byte { + return append(b, v...) +} + +func (enc *Encoder) encodeTableHeader(ctx encoderCtx, b []byte) ([]byte, error) { + if len(ctx.parentKey) == 0 { + return b, nil + } + + b = enc.encodeComment(ctx.indent, ctx.options.comment, b) + + b = enc.commented(ctx.commented, b) + + b = enc.indent(ctx.indent, b) + + b = append(b, '[') + + b = enc.encodeKey(b, ctx.parentKey[0]) + + for _, k := range ctx.parentKey[1:] { + b = append(b, '.') + b = enc.encodeKey(b, k) + } + + b = append(b, "]\n"...) + + return b, nil +} + +//nolint:cyclop +func (enc *Encoder) encodeKey(b []byte, k string) []byte { + needsQuotation := false + cannotUseLiteral := false + + if len(k) == 0 { + return append(b, "''"...) + } + + for _, c := range k { + if (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c >= '0' && c <= '9') || c == '-' || c == '_' { + continue + } + + if c == literalQuote { + cannotUseLiteral = true + } + + needsQuotation = true + } + + if needsQuotation && needsQuoting(k) { + cannotUseLiteral = true + } + + switch { + case cannotUseLiteral: + return enc.encodeQuotedString(false, b, k) + case needsQuotation: + return enc.encodeLiteralString(b, k) + default: + return enc.encodeUnquotedKey(b, k) + } +} + +func (enc *Encoder) keyToString(k reflect.Value) (string, error) { + keyType := k.Type() + switch { + case keyType.Kind() == reflect.String: + return k.String(), nil + + case keyType.Implements(textMarshalerType): + keyB, err := k.Interface().(encoding.TextMarshaler).MarshalText() + if err != nil { + return "", fmt.Errorf("toml: error marshalling key %v from text: %w", k, err) + } + return string(keyB), nil + + case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64: + return strconv.FormatInt(k.Int(), 10), nil + + case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64: + return strconv.FormatUint(k.Uint(), 10), nil + + case keyType.Kind() == reflect.Float32: + return strconv.FormatFloat(k.Float(), 'f', -1, 32), nil + + case keyType.Kind() == reflect.Float64: + return strconv.FormatFloat(k.Float(), 'f', -1, 64), nil + } + return "", fmt.Errorf("toml: type %s is not supported as a map key", keyType.Kind()) +} + +func (enc *Encoder) encodeMap(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) { + var ( + t table + emptyValueOptions valueOptions + ) + + iter := v.MapRange() + for iter.Next() { + v := iter.Value() + + if isNil(v) { + continue + } + + k, err := enc.keyToString(iter.Key()) + if err != nil { + return nil, err + } + + if willConvertToTableOrArrayTable(ctx, v) { + t.pushTable(k, v, emptyValueOptions) + } else { + t.pushKV(k, v, emptyValueOptions) + } + } + + sortEntriesByKey(t.kvs) + sortEntriesByKey(t.tables) + + return enc.encodeTable(b, ctx, t) +} + +func sortEntriesByKey(e []entry) { + slices.SortFunc(e, func(a, b entry) int { + return strings.Compare(a.Key, b.Key) + }) +} + +type entry struct { + Key string + Value reflect.Value + Options valueOptions +} + +type table struct { + kvs []entry + tables []entry +} + +func (t *table) pushKV(k string, v reflect.Value, options valueOptions) { + for _, e := range t.kvs { + if e.Key == k { + return + } + } + + t.kvs = append(t.kvs, entry{Key: k, Value: v, Options: options}) +} + +func (t *table) pushTable(k string, v reflect.Value, options valueOptions) { + for _, e := range t.tables { + if e.Key == k { + return + } + } + t.tables = append(t.tables, entry{Key: k, Value: v, Options: options}) +} + +func walkStruct(ctx encoderCtx, t *table, v reflect.Value) { + // TODO: cache this + typ := v.Type() + for i := 0; i < typ.NumField(); i++ { + fieldType := typ.Field(i) + + // only consider exported fields + if fieldType.PkgPath != "" { + continue + } + + tag := fieldType.Tag.Get("toml") + + // special field name to skip field + if tag == "-" { + continue + } + + k, opts := parseTag(tag) + if !isValidName(k) { + k = "" + } + + f := v.Field(i) + + if k == "" { + if fieldType.Anonymous { + if fieldType.Type.Kind() == reflect.Struct { + walkStruct(ctx, t, f) + } else if fieldType.Type.Kind() == reflect.Ptr && !f.IsNil() && f.Elem().Kind() == reflect.Struct { + walkStruct(ctx, t, f.Elem()) + } + continue + } else { + k = fieldType.Name + } + } + + if isNil(f) { + continue + } + + options := valueOptions{ + multiline: opts.multiline, + omitempty: opts.omitempty, + commented: opts.commented, + comment: fieldType.Tag.Get("comment"), + } + + if opts.inline || !willConvertToTableOrArrayTable(ctx, f) { + t.pushKV(k, f, options) + } else { + t.pushTable(k, f, options) + } + } +} + +func (enc *Encoder) encodeStruct(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) { + var t table + + walkStruct(ctx, &t, v) + + return enc.encodeTable(b, ctx, t) +} + +func (enc *Encoder) encodeComment(indent int, comment string, b []byte) []byte { + for len(comment) > 0 { + var line string + idx := strings.IndexByte(comment, '\n') + if idx >= 0 { + line = comment[:idx] + comment = comment[idx+1:] + } else { + line = comment + comment = "" + } + b = enc.indent(indent, b) + b = append(b, "# "...) + b = append(b, line...) + b = append(b, '\n') + } + return b +} + +func isValidName(s string) bool { + if s == "" { + return false + } + for _, c := range s { + switch { + case strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c): + // Backslash and quote chars are reserved, but + // otherwise any punctuation chars are allowed + // in a tag name. + case !unicode.IsLetter(c) && !unicode.IsDigit(c): + return false + } + } + return true +} + +type tagOptions struct { + multiline bool + inline bool + omitempty bool + commented bool +} + +func parseTag(tag string) (string, tagOptions) { + opts := tagOptions{} + + idx := strings.Index(tag, ",") + if idx == -1 { + return tag, opts + } + + raw := tag[idx+1:] + tag = string(tag[:idx]) + for raw != "" { + var o string + i := strings.Index(raw, ",") + if i >= 0 { + o, raw = raw[:i], raw[i+1:] + } else { + o, raw = raw, "" + } + switch o { + case "multiline": + opts.multiline = true + case "inline": + opts.inline = true + case "omitempty": + opts.omitempty = true + case "commented": + opts.commented = true + } + } + + return tag, opts +} + +func (enc *Encoder) encodeTable(b []byte, ctx encoderCtx, t table) ([]byte, error) { + var err error + + ctx.shiftKey() + + if ctx.insideKv || (ctx.inline && !ctx.isRoot()) { + return enc.encodeTableInline(b, ctx, t) + } + + if !ctx.skipTableHeader { + b, err = enc.encodeTableHeader(ctx, b) + if err != nil { + return nil, err + } + + if enc.indentTables && len(ctx.parentKey) > 0 { + ctx.indent++ + } + } + ctx.skipTableHeader = false + + hasNonEmptyKV := false + for _, kv := range t.kvs { + if shouldOmitEmpty(kv.Options, kv.Value) { + continue + } + hasNonEmptyKV = true + + ctx.setKey(kv.Key) + ctx2 := ctx + ctx2.commented = kv.Options.commented || ctx2.commented + + b, err = enc.encodeKv(b, ctx2, kv.Options, kv.Value) + if err != nil { + return nil, err + } + + b = append(b, '\n') + } + + first := true + for _, table := range t.tables { + if shouldOmitEmpty(table.Options, table.Value) { + continue + } + if first { + first = false + if hasNonEmptyKV { + b = append(b, '\n') + } + } else { + b = append(b, "\n"...) + } + + ctx.setKey(table.Key) + + ctx.options = table.Options + ctx2 := ctx + ctx2.commented = ctx2.commented || ctx.options.commented + + b, err = enc.encode(b, ctx2, table.Value) + if err != nil { + return nil, err + } + } + + return b, nil +} + +func (enc *Encoder) encodeTableInline(b []byte, ctx encoderCtx, t table) ([]byte, error) { + var err error + + b = append(b, '{') + + first := true + for _, kv := range t.kvs { + if shouldOmitEmpty(kv.Options, kv.Value) { + continue + } + + if first { + first = false + } else { + b = append(b, `, `...) + } + + ctx.setKey(kv.Key) + + b, err = enc.encodeKv(b, ctx, kv.Options, kv.Value) + if err != nil { + return nil, err + } + } + + if len(t.tables) > 0 { + panic("inline table cannot contain nested tables, only key-values") + } + + b = append(b, "}"...) + + return b, nil +} + +func willConvertToTable(ctx encoderCtx, v reflect.Value) bool { + if !v.IsValid() { + return false + } + if v.Type() == timeType || v.Type().Implements(textMarshalerType) || (v.Kind() != reflect.Ptr && v.CanAddr() && reflect.PointerTo(v.Type()).Implements(textMarshalerType)) { + return false + } + + t := v.Type() + switch t.Kind() { + case reflect.Map, reflect.Struct: + return !ctx.inline + case reflect.Interface: + return willConvertToTable(ctx, v.Elem()) + case reflect.Ptr: + if v.IsNil() { + return false + } + + return willConvertToTable(ctx, v.Elem()) + default: + return false + } +} + +func willConvertToTableOrArrayTable(ctx encoderCtx, v reflect.Value) bool { + if ctx.insideKv { + return false + } + t := v.Type() + + if t.Kind() == reflect.Interface { + return willConvertToTableOrArrayTable(ctx, v.Elem()) + } + + if t.Kind() == reflect.Slice || t.Kind() == reflect.Array { + if v.Len() == 0 { + // An empty slice should be a kv = []. + return false + } + + for i := 0; i < v.Len(); i++ { + t := willConvertToTable(ctx, v.Index(i)) + + if !t { + return false + } + } + + return true + } + + return willConvertToTable(ctx, v) +} + +func (enc *Encoder) encodeSlice(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) { + if v.Len() == 0 { + b = append(b, "[]"...) + + return b, nil + } + + if willConvertToTableOrArrayTable(ctx, v) { + return enc.encodeSliceAsArrayTable(b, ctx, v) + } + + return enc.encodeSliceAsArray(b, ctx, v) +} + +// caller should have checked that v is a slice that only contains values that +// encode into tables. +func (enc *Encoder) encodeSliceAsArrayTable(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) { + ctx.shiftKey() + + scratch := make([]byte, 0, 64) + + scratch = enc.commented(ctx.commented, scratch) + + if enc.indentTables { + scratch = enc.indent(ctx.indent, scratch) + } + + scratch = append(scratch, "[["...) + + for i, k := range ctx.parentKey { + if i > 0 { + scratch = append(scratch, '.') + } + + scratch = enc.encodeKey(scratch, k) + } + + scratch = append(scratch, "]]\n"...) + ctx.skipTableHeader = true + + b = enc.encodeComment(ctx.indent, ctx.options.comment, b) + + if enc.indentTables { + ctx.indent++ + } + + for i := 0; i < v.Len(); i++ { + if i != 0 { + b = append(b, "\n"...) + } + + b = append(b, scratch...) + + var err error + b, err = enc.encode(b, ctx, v.Index(i)) + if err != nil { + return nil, err + } + } + + return b, nil +} + +func (enc *Encoder) encodeSliceAsArray(b []byte, ctx encoderCtx, v reflect.Value) ([]byte, error) { + multiline := ctx.options.multiline || enc.arraysMultiline + separator := ", " + + b = append(b, '[') + + subCtx := ctx + subCtx.options = valueOptions{} + + if multiline { + separator = ",\n" + + b = append(b, '\n') + + subCtx.indent++ + } + + var err error + first := true + + for i := 0; i < v.Len(); i++ { + if first { + first = false + } else { + b = append(b, separator...) + } + + if multiline { + b = enc.indent(subCtx.indent, b) + } + + b, err = enc.encode(b, subCtx, v.Index(i)) + if err != nil { + return nil, err + } + } + + if multiline { + b = append(b, '\n') + b = enc.indent(ctx.indent, b) + } + + b = append(b, ']') + + return b, nil +} + +func (enc *Encoder) indent(level int, b []byte) []byte { + for i := 0; i < level; i++ { + b = append(b, enc.indentSymbol...) + } + + return b +} diff --git a/vendor/github.com/pelletier/go-toml/v2/strict.go b/vendor/github.com/pelletier/go-toml/v2/strict.go new file mode 100644 index 0000000000..802e7e4d15 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/strict.go @@ -0,0 +1,107 @@ +package toml + +import ( + "github.com/pelletier/go-toml/v2/internal/danger" + "github.com/pelletier/go-toml/v2/internal/tracker" + "github.com/pelletier/go-toml/v2/unstable" +) + +type strict struct { + Enabled bool + + // Tracks the current key being processed. + key tracker.KeyTracker + + missing []unstable.ParserError +} + +func (s *strict) EnterTable(node *unstable.Node) { + if !s.Enabled { + return + } + + s.key.UpdateTable(node) +} + +func (s *strict) EnterArrayTable(node *unstable.Node) { + if !s.Enabled { + return + } + + s.key.UpdateArrayTable(node) +} + +func (s *strict) EnterKeyValue(node *unstable.Node) { + if !s.Enabled { + return + } + + s.key.Push(node) +} + +func (s *strict) ExitKeyValue(node *unstable.Node) { + if !s.Enabled { + return + } + + s.key.Pop(node) +} + +func (s *strict) MissingTable(node *unstable.Node) { + if !s.Enabled { + return + } + + s.missing = append(s.missing, unstable.ParserError{ + Highlight: keyLocation(node), + Message: "missing table", + Key: s.key.Key(), + }) +} + +func (s *strict) MissingField(node *unstable.Node) { + if !s.Enabled { + return + } + + s.missing = append(s.missing, unstable.ParserError{ + Highlight: keyLocation(node), + Message: "missing field", + Key: s.key.Key(), + }) +} + +func (s *strict) Error(doc []byte) error { + if !s.Enabled || len(s.missing) == 0 { + return nil + } + + err := &StrictMissingError{ + Errors: make([]DecodeError, 0, len(s.missing)), + } + + for _, derr := range s.missing { + derr := derr + err.Errors = append(err.Errors, *wrapDecodeError(doc, &derr)) + } + + return err +} + +func keyLocation(node *unstable.Node) []byte { + k := node.Key() + + hasOne := k.Next() + if !hasOne { + panic("should not be called with empty key") + } + + start := k.Node().Data + end := k.Node().Data + + for k.Next() { + end = k.Node().Data + } + + return danger.BytesRange(start, end) +} diff --git a/vendor/github.com/pelletier/go-toml/v2/toml.abnf b/vendor/github.com/pelletier/go-toml/v2/toml.abnf new file mode 100644 index 0000000000..473f3749e8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/toml.abnf @@ -0,0 +1,243 @@ +;; This document describes TOML's syntax, using the ABNF format (defined in +;; RFC 5234 -- https://www.ietf.org/rfc/rfc5234.txt). +;; +;; All valid TOML documents will match this description, however certain +;; invalid documents would need to be rejected as per the semantics described +;; in the supporting text description. + +;; It is possible to try this grammar interactively, using instaparse. +;; http://instaparse.mojombo.com/ +;; +;; To do so, in the lower right, click on Options and change `:input-format` to +;; ':abnf'. Then paste this entire ABNF document into the grammar entry box +;; (above the options). Then you can type or paste a sample TOML document into +;; the beige box on the left. Tada! + +;; Overall Structure + +toml = expression *( newline expression ) + +expression = ws [ comment ] +expression =/ ws keyval ws [ comment ] +expression =/ ws table ws [ comment ] + +;; Whitespace + +ws = *wschar +wschar = %x20 ; Space +wschar =/ %x09 ; Horizontal tab + +;; Newline + +newline = %x0A ; LF +newline =/ %x0D.0A ; CRLF + +;; Comment + +comment-start-symbol = %x23 ; # +non-ascii = %x80-D7FF / %xE000-10FFFF +non-eol = %x09 / %x20-7F / non-ascii + +comment = comment-start-symbol *non-eol + +;; Key-Value pairs + +keyval = key keyval-sep val + +key = simple-key / dotted-key +simple-key = quoted-key / unquoted-key + +unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ +quoted-key = basic-string / literal-string +dotted-key = simple-key 1*( dot-sep simple-key ) + +dot-sep = ws %x2E ws ; . Period +keyval-sep = ws %x3D ws ; = + +val = string / boolean / array / inline-table / date-time / float / integer + +;; String + +string = ml-basic-string / basic-string / ml-literal-string / literal-string + +;; Basic String + +basic-string = quotation-mark *basic-char quotation-mark + +quotation-mark = %x22 ; " + +basic-char = basic-unescaped / escaped +basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii +escaped = escape escape-seq-char + +escape = %x5C ; \ +escape-seq-char = %x22 ; " quotation mark U+0022 +escape-seq-char =/ %x5C ; \ reverse solidus U+005C +escape-seq-char =/ %x62 ; b backspace U+0008 +escape-seq-char =/ %x66 ; f form feed U+000C +escape-seq-char =/ %x6E ; n line feed U+000A +escape-seq-char =/ %x72 ; r carriage return U+000D +escape-seq-char =/ %x74 ; t tab U+0009 +escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX +escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX + +;; Multiline Basic String + +ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body + ml-basic-string-delim +ml-basic-string-delim = 3quotation-mark +ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ] + +mlb-content = mlb-char / newline / mlb-escaped-nl +mlb-char = mlb-unescaped / escaped +mlb-quotes = 1*2quotation-mark +mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii +mlb-escaped-nl = escape ws newline *( wschar / newline ) + +;; Literal String + +literal-string = apostrophe *literal-char apostrophe + +apostrophe = %x27 ; ' apostrophe + +literal-char = %x09 / %x20-26 / %x28-7E / non-ascii + +;; Multiline Literal String + +ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body + ml-literal-string-delim +ml-literal-string-delim = 3apostrophe +ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ] + +mll-content = mll-char / newline +mll-char = %x09 / %x20-26 / %x28-7E / non-ascii +mll-quotes = 1*2apostrophe + +;; Integer + +integer = dec-int / hex-int / oct-int / bin-int + +minus = %x2D ; - +plus = %x2B ; + +underscore = %x5F ; _ +digit1-9 = %x31-39 ; 1-9 +digit0-7 = %x30-37 ; 0-7 +digit0-1 = %x30-31 ; 0-1 + +hex-prefix = %x30.78 ; 0x +oct-prefix = %x30.6F ; 0o +bin-prefix = %x30.62 ; 0b + +dec-int = [ minus / plus ] unsigned-dec-int +unsigned-dec-int = DIGIT / digit1-9 1*( DIGIT / underscore DIGIT ) + +hex-int = hex-prefix HEXDIG *( HEXDIG / underscore HEXDIG ) +oct-int = oct-prefix digit0-7 *( digit0-7 / underscore digit0-7 ) +bin-int = bin-prefix digit0-1 *( digit0-1 / underscore digit0-1 ) + +;; Float + +float = float-int-part ( exp / frac [ exp ] ) +float =/ special-float + +float-int-part = dec-int +frac = decimal-point zero-prefixable-int +decimal-point = %x2E ; . +zero-prefixable-int = DIGIT *( DIGIT / underscore DIGIT ) + +exp = "e" float-exp-part +float-exp-part = [ minus / plus ] zero-prefixable-int + +special-float = [ minus / plus ] ( inf / nan ) +inf = %x69.6e.66 ; inf +nan = %x6e.61.6e ; nan + +;; Boolean + +boolean = true / false + +true = %x74.72.75.65 ; true +false = %x66.61.6C.73.65 ; false + +;; Date and Time (as defined in RFC 3339) + +date-time = offset-date-time / local-date-time / local-date / local-time + +date-fullyear = 4DIGIT +date-month = 2DIGIT ; 01-12 +date-mday = 2DIGIT ; 01-28, 01-29, 01-30, 01-31 based on month/year +time-delim = "T" / %x20 ; T, t, or space +time-hour = 2DIGIT ; 00-23 +time-minute = 2DIGIT ; 00-59 +time-second = 2DIGIT ; 00-58, 00-59, 00-60 based on leap second rules +time-secfrac = "." 1*DIGIT +time-numoffset = ( "+" / "-" ) time-hour ":" time-minute +time-offset = "Z" / time-numoffset + +partial-time = time-hour ":" time-minute ":" time-second [ time-secfrac ] +full-date = date-fullyear "-" date-month "-" date-mday +full-time = partial-time time-offset + +;; Offset Date-Time + +offset-date-time = full-date time-delim full-time + +;; Local Date-Time + +local-date-time = full-date time-delim partial-time + +;; Local Date + +local-date = full-date + +;; Local Time + +local-time = partial-time + +;; Array + +array = array-open [ array-values ] ws-comment-newline array-close + +array-open = %x5B ; [ +array-close = %x5D ; ] + +array-values = ws-comment-newline val ws-comment-newline array-sep array-values +array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ] + +array-sep = %x2C ; , Comma + +ws-comment-newline = *( wschar / [ comment ] newline ) + +;; Table + +table = std-table / array-table + +;; Standard Table + +std-table = std-table-open key std-table-close + +std-table-open = %x5B ws ; [ Left square bracket +std-table-close = ws %x5D ; ] Right square bracket + +;; Inline Table + +inline-table = inline-table-open [ inline-table-keyvals ] inline-table-close + +inline-table-open = %x7B ws ; { +inline-table-close = ws %x7D ; } +inline-table-sep = ws %x2C ws ; , Comma + +inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ] + +;; Array Table + +array-table = array-table-open key array-table-close + +array-table-open = %x5B.5B ws ; [[ Double left square bracket +array-table-close = ws %x5D.5D ; ]] Double right square bracket + +;; Built-in ABNF terms, reproduced here for clarity + +ALPHA = %x41-5A / %x61-7A ; A-Z / a-z +DIGIT = %x30-39 ; 0-9 +HEXDIG = DIGIT / "A" / "B" / "C" / "D" / "E" / "F" diff --git a/vendor/github.com/pelletier/go-toml/v2/types.go b/vendor/github.com/pelletier/go-toml/v2/types.go new file mode 100644 index 0000000000..3c6b8fe570 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/types.go @@ -0,0 +1,14 @@ +package toml + +import ( + "encoding" + "reflect" + "time" +) + +var timeType = reflect.TypeOf((*time.Time)(nil)).Elem() +var textMarshalerType = reflect.TypeOf((*encoding.TextMarshaler)(nil)).Elem() +var textUnmarshalerType = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem() +var mapStringInterfaceType = reflect.TypeOf(map[string]interface{}(nil)) +var sliceInterfaceType = reflect.TypeOf([]interface{}(nil)) +var stringType = reflect.TypeOf("") diff --git a/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go new file mode 100644 index 0000000000..c3df8bee1c --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unmarshaler.go @@ -0,0 +1,1334 @@ +package toml + +import ( + "encoding" + "errors" + "fmt" + "io" + "math" + "reflect" + "strconv" + "strings" + "sync/atomic" + "time" + + "github.com/pelletier/go-toml/v2/internal/danger" + "github.com/pelletier/go-toml/v2/internal/tracker" + "github.com/pelletier/go-toml/v2/unstable" +) + +// Unmarshal deserializes a TOML document into a Go value. +// +// It is a shortcut for Decoder.Decode() with the default options. +func Unmarshal(data []byte, v interface{}) error { + d := decoder{} + d.p.Reset(data) + return d.FromParser(v) +} + +// Decoder reads and decode a TOML document from an input stream. +type Decoder struct { + // input + r io.Reader + + // global settings + strict bool + + // toggles unmarshaler interface + unmarshalerInterface bool +} + +// NewDecoder creates a new Decoder that will read from r. +func NewDecoder(r io.Reader) *Decoder { + return &Decoder{r: r} +} + +// DisallowUnknownFields causes the Decoder to return an error when the +// destination is a struct and the input contains a key that does not match a +// non-ignored field. +// +// In that case, the Decoder returns a StrictMissingError that can be used to +// retrieve the individual errors as well as generate a human readable +// description of the missing fields. +func (d *Decoder) DisallowUnknownFields() *Decoder { + d.strict = true + return d +} + +// EnableUnmarshalerInterface allows to enable unmarshaler interface. +// +// With this feature enabled, types implementing the unstable/Unmarshaler +// interface can be decoded from any structure of the document. It allows types +// that don't have a straightfoward TOML representation to provide their own +// decoding logic. +// +// Currently, types can only decode from a single value. Tables and array tables +// are not supported. +// +// *Unstable:* This method does not follow the compatibility guarantees of +// semver. It can be changed or removed without a new major version being +// issued. +func (d *Decoder) EnableUnmarshalerInterface() *Decoder { + d.unmarshalerInterface = true + return d +} + +// Decode the whole content of r into v. +// +// By default, values in the document that don't exist in the target Go value +// are ignored. See Decoder.DisallowUnknownFields() to change this behavior. +// +// When a TOML local date, time, or date-time is decoded into a time.Time, its +// value is represented in time.Local timezone. Otherwise the appropriate Local* +// structure is used. For time values, precision up to the nanosecond is +// supported by truncating extra digits. +// +// Empty tables decoded in an interface{} create an empty initialized +// map[string]interface{}. +// +// Types implementing the encoding.TextUnmarshaler interface are decoded from a +// TOML string. +// +// When decoding a number, go-toml will return an error if the number is out of +// bounds for the target type (which includes negative numbers when decoding +// into an unsigned int). +// +// If an error occurs while decoding the content of the document, this function +// returns a toml.DecodeError, providing context about the issue. When using +// strict mode and a field is missing, a `toml.StrictMissingError` is +// returned. In any other case, this function returns a standard Go error. +// +// # Type mapping +// +// List of supported TOML types and their associated accepted Go types: +// +// String -> string +// Integer -> uint*, int*, depending on size +// Float -> float*, depending on size +// Boolean -> bool +// Offset Date-Time -> time.Time +// Local Date-time -> LocalDateTime, time.Time +// Local Date -> LocalDate, time.Time +// Local Time -> LocalTime, time.Time +// Array -> slice and array, depending on elements types +// Table -> map and struct +// Inline Table -> same as Table +// Array of Tables -> same as Array and Table +func (d *Decoder) Decode(v interface{}) error { + b, err := io.ReadAll(d.r) + if err != nil { + return fmt.Errorf("toml: %w", err) + } + + dec := decoder{ + strict: strict{ + Enabled: d.strict, + }, + unmarshalerInterface: d.unmarshalerInterface, + } + dec.p.Reset(b) + + return dec.FromParser(v) +} + +type decoder struct { + // Which parser instance in use for this decoding session. + p unstable.Parser + + // Flag indicating that the current expression is stashed. + // If set to true, calling nextExpr will not actually pull a new expression + // but turn off the flag instead. + stashedExpr bool + + // Skip expressions until a table is found. This is set to true when a + // table could not be created (missing field in map), so all KV expressions + // need to be skipped. + skipUntilTable bool + + // Flag indicating that the current array/slice table should be cleared because + // it is the first encounter of an array table. + clearArrayTable bool + + // Tracks position in Go arrays. + // This is used when decoding [[array tables]] into Go arrays. Given array + // tables are separate TOML expression, we need to keep track of where we + // are at in the Go array, as we can't just introspect its size. + arrayIndexes map[reflect.Value]int + + // Tracks keys that have been seen, with which type. + seen tracker.SeenTracker + + // Strict mode + strict strict + + // Flag that enables/disables unmarshaler interface. + unmarshalerInterface bool + + // Current context for the error. + errorContext *errorContext +} + +type errorContext struct { + Struct reflect.Type + Field []int +} + +func (d *decoder) typeMismatchError(toml string, target reflect.Type) error { + return fmt.Errorf("toml: %s", d.typeMismatchString(toml, target)) +} + +func (d *decoder) typeMismatchString(toml string, target reflect.Type) string { + if d.errorContext != nil && d.errorContext.Struct != nil { + ctx := d.errorContext + f := ctx.Struct.FieldByIndex(ctx.Field) + return fmt.Sprintf("cannot decode TOML %s into struct field %s.%s of type %s", toml, ctx.Struct, f.Name, f.Type) + } + return fmt.Sprintf("cannot decode TOML %s into a Go value of type %s", toml, target) +} + +func (d *decoder) expr() *unstable.Node { + return d.p.Expression() +} + +func (d *decoder) nextExpr() bool { + if d.stashedExpr { + d.stashedExpr = false + return true + } + return d.p.NextExpression() +} + +func (d *decoder) stashExpr() { + d.stashedExpr = true +} + +func (d *decoder) arrayIndex(shouldAppend bool, v reflect.Value) int { + if d.arrayIndexes == nil { + d.arrayIndexes = make(map[reflect.Value]int, 1) + } + + idx, ok := d.arrayIndexes[v] + + if !ok { + d.arrayIndexes[v] = 0 + } else if shouldAppend { + idx++ + d.arrayIndexes[v] = idx + } + + return idx +} + +func (d *decoder) FromParser(v interface{}) error { + r := reflect.ValueOf(v) + if r.Kind() != reflect.Ptr { + return fmt.Errorf("toml: decoding can only be performed into a pointer, not %s", r.Kind()) + } + + if r.IsNil() { + return fmt.Errorf("toml: decoding pointer target cannot be nil") + } + + r = r.Elem() + if r.Kind() == reflect.Interface && r.IsNil() { + newMap := map[string]interface{}{} + r.Set(reflect.ValueOf(newMap)) + } + + err := d.fromParser(r) + if err == nil { + return d.strict.Error(d.p.Data()) + } + + var e *unstable.ParserError + if errors.As(err, &e) { + return wrapDecodeError(d.p.Data(), e) + } + + return err +} + +func (d *decoder) fromParser(root reflect.Value) error { + for d.nextExpr() { + err := d.handleRootExpression(d.expr(), root) + if err != nil { + return err + } + } + + return d.p.Error() +} + +/* +Rules for the unmarshal code: + +- The stack is used to keep track of which values need to be set where. +- handle* functions <=> switch on a given unstable.Kind. +- unmarshalX* functions need to unmarshal a node of kind X. +- An "object" is either a struct or a map. +*/ + +func (d *decoder) handleRootExpression(expr *unstable.Node, v reflect.Value) error { + var x reflect.Value + var err error + var first bool // used for to clear array tables on first use + + if !(d.skipUntilTable && expr.Kind == unstable.KeyValue) { + first, err = d.seen.CheckExpression(expr) + if err != nil { + return err + } + } + + switch expr.Kind { + case unstable.KeyValue: + if d.skipUntilTable { + return nil + } + x, err = d.handleKeyValue(expr, v) + case unstable.Table: + d.skipUntilTable = false + d.strict.EnterTable(expr) + x, err = d.handleTable(expr.Key(), v) + case unstable.ArrayTable: + d.skipUntilTable = false + d.strict.EnterArrayTable(expr) + d.clearArrayTable = first + x, err = d.handleArrayTable(expr.Key(), v) + default: + panic(fmt.Errorf("parser should not permit expression of kind %s at document root", expr.Kind)) + } + + if d.skipUntilTable { + if expr.Kind == unstable.Table || expr.Kind == unstable.ArrayTable { + d.strict.MissingTable(expr) + } + } else if err == nil && x.IsValid() { + v.Set(x) + } + + return err +} + +func (d *decoder) handleArrayTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) { + if key.Next() { + return d.handleArrayTablePart(key, v) + } + return d.handleKeyValues(v) +} + +func (d *decoder) handleArrayTableCollectionLast(key unstable.Iterator, v reflect.Value) (reflect.Value, error) { + switch v.Kind() { + case reflect.Interface: + elem := v.Elem() + if !elem.IsValid() { + elem = reflect.New(sliceInterfaceType).Elem() + elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16)) + } else if elem.Kind() == reflect.Slice { + if elem.Type() != sliceInterfaceType { + elem = reflect.New(sliceInterfaceType).Elem() + elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16)) + } else if !elem.CanSet() { + nelem := reflect.New(sliceInterfaceType).Elem() + nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap())) + reflect.Copy(nelem, elem) + elem = nelem + } + if d.clearArrayTable && elem.Len() > 0 { + elem.SetLen(0) + d.clearArrayTable = false + } + } + return d.handleArrayTableCollectionLast(key, elem) + case reflect.Ptr: + elem := v.Elem() + if !elem.IsValid() { + ptr := reflect.New(v.Type().Elem()) + v.Set(ptr) + elem = ptr.Elem() + } + + elem, err := d.handleArrayTableCollectionLast(key, elem) + if err != nil { + return reflect.Value{}, err + } + v.Elem().Set(elem) + + return v, nil + case reflect.Slice: + if d.clearArrayTable && v.Len() > 0 { + v.SetLen(0) + d.clearArrayTable = false + } + elemType := v.Type().Elem() + var elem reflect.Value + if elemType.Kind() == reflect.Interface { + elem = makeMapStringInterface() + } else { + elem = reflect.New(elemType).Elem() + } + elem2, err := d.handleArrayTable(key, elem) + if err != nil { + return reflect.Value{}, err + } + if elem2.IsValid() { + elem = elem2 + } + return reflect.Append(v, elem), nil + case reflect.Array: + idx := d.arrayIndex(true, v) + if idx >= v.Len() { + return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx) + } + elem := v.Index(idx) + _, err := d.handleArrayTable(key, elem) + return v, err + default: + return reflect.Value{}, d.typeMismatchError("array table", v.Type()) + } +} + +// When parsing an array table expression, each part of the key needs to be +// evaluated like a normal key, but if it returns a collection, it also needs to +// point to the last element of the collection. Unless it is the last part of +// the key, then it needs to create a new element at the end. +func (d *decoder) handleArrayTableCollection(key unstable.Iterator, v reflect.Value) (reflect.Value, error) { + if key.IsLast() { + return d.handleArrayTableCollectionLast(key, v) + } + + switch v.Kind() { + case reflect.Ptr: + elem := v.Elem() + if !elem.IsValid() { + ptr := reflect.New(v.Type().Elem()) + v.Set(ptr) + elem = ptr.Elem() + } + + elem, err := d.handleArrayTableCollection(key, elem) + if err != nil { + return reflect.Value{}, err + } + if elem.IsValid() { + v.Elem().Set(elem) + } + + return v, nil + case reflect.Slice: + elem := v.Index(v.Len() - 1) + x, err := d.handleArrayTable(key, elem) + if err != nil || d.skipUntilTable { + return reflect.Value{}, err + } + if x.IsValid() { + elem.Set(x) + } + + return v, err + case reflect.Array: + idx := d.arrayIndex(false, v) + if idx >= v.Len() { + return v, fmt.Errorf("%s at position %d", d.typeMismatchError("array table", v.Type()), idx) + } + elem := v.Index(idx) + _, err := d.handleArrayTable(key, elem) + return v, err + } + + return d.handleArrayTable(key, v) +} + +func (d *decoder) handleKeyPart(key unstable.Iterator, v reflect.Value, nextFn handlerFn, makeFn valueMakerFn) (reflect.Value, error) { + var rv reflect.Value + + // First, dispatch over v to make sure it is a valid object. + // There is no guarantee over what it could be. + switch v.Kind() { + case reflect.Ptr: + elem := v.Elem() + if !elem.IsValid() { + v.Set(reflect.New(v.Type().Elem())) + } + elem = v.Elem() + return d.handleKeyPart(key, elem, nextFn, makeFn) + case reflect.Map: + vt := v.Type() + + // Create the key for the map element. Convert to key type. + mk, err := d.keyFromData(vt.Key(), key.Node().Data) + if err != nil { + return reflect.Value{}, err + } + + // If the map does not exist, create it. + if v.IsNil() { + vt := v.Type() + v = reflect.MakeMap(vt) + rv = v + } + + mv := v.MapIndex(mk) + set := false + if !mv.IsValid() { + // If there is no value in the map, create a new one according to + // the map type. If the element type is interface, create either a + // map[string]interface{} or a []interface{} depending on whether + // this is the last part of the array table key. + + t := vt.Elem() + if t.Kind() == reflect.Interface { + mv = makeFn() + } else { + mv = reflect.New(t).Elem() + } + set = true + } else if mv.Kind() == reflect.Interface { + mv = mv.Elem() + if !mv.IsValid() { + mv = makeFn() + } + set = true + } else if !mv.CanAddr() { + vt := v.Type() + t := vt.Elem() + oldmv := mv + mv = reflect.New(t).Elem() + mv.Set(oldmv) + set = true + } + + x, err := nextFn(key, mv) + if err != nil { + return reflect.Value{}, err + } + + if x.IsValid() { + mv = x + set = true + } + + if set { + v.SetMapIndex(mk, mv) + } + case reflect.Struct: + path, found := structFieldPath(v, string(key.Node().Data)) + if !found { + d.skipUntilTable = true + return reflect.Value{}, nil + } + + if d.errorContext == nil { + d.errorContext = new(errorContext) + } + t := v.Type() + d.errorContext.Struct = t + d.errorContext.Field = path + + f := fieldByIndex(v, path) + x, err := nextFn(key, f) + if err != nil || d.skipUntilTable { + return reflect.Value{}, err + } + if x.IsValid() { + f.Set(x) + } + d.errorContext.Field = nil + d.errorContext.Struct = nil + case reflect.Interface: + if v.Elem().IsValid() { + v = v.Elem() + } else { + v = makeMapStringInterface() + } + + x, err := d.handleKeyPart(key, v, nextFn, makeFn) + if err != nil { + return reflect.Value{}, err + } + if x.IsValid() { + v = x + } + rv = v + default: + panic(fmt.Errorf("unhandled part: %s", v.Kind())) + } + + return rv, nil +} + +// HandleArrayTablePart navigates the Go structure v using the key v. It is +// only used for the prefix (non-last) parts of an array-table. When +// encountering a collection, it should go to the last element. +func (d *decoder) handleArrayTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) { + var makeFn valueMakerFn + if key.IsLast() { + makeFn = makeSliceInterface + } else { + makeFn = makeMapStringInterface + } + return d.handleKeyPart(key, v, d.handleArrayTableCollection, makeFn) +} + +// HandleTable returns a reference when it has checked the next expression but +// cannot handle it. +func (d *decoder) handleTable(key unstable.Iterator, v reflect.Value) (reflect.Value, error) { + if v.Kind() == reflect.Slice { + if v.Len() == 0 { + return reflect.Value{}, unstable.NewParserError(key.Node().Data, "cannot store a table in a slice") + } + elem := v.Index(v.Len() - 1) + x, err := d.handleTable(key, elem) + if err != nil { + return reflect.Value{}, err + } + if x.IsValid() { + elem.Set(x) + } + return reflect.Value{}, nil + } + if key.Next() { + // Still scoping the key + return d.handleTablePart(key, v) + } + // Done scoping the key. + // Now handle all the key-value expressions in this table. + return d.handleKeyValues(v) +} + +// Handle root expressions until the end of the document or the next +// non-key-value. +func (d *decoder) handleKeyValues(v reflect.Value) (reflect.Value, error) { + var rv reflect.Value + for d.nextExpr() { + expr := d.expr() + if expr.Kind != unstable.KeyValue { + // Stash the expression so that fromParser can just loop and use + // the right handler. + // We could just recurse ourselves here, but at least this gives a + // chance to pop the stack a bit. + d.stashExpr() + break + } + + _, err := d.seen.CheckExpression(expr) + if err != nil { + return reflect.Value{}, err + } + + x, err := d.handleKeyValue(expr, v) + if err != nil { + return reflect.Value{}, err + } + if x.IsValid() { + v = x + rv = x + } + } + return rv, nil +} + +type ( + handlerFn func(key unstable.Iterator, v reflect.Value) (reflect.Value, error) + valueMakerFn func() reflect.Value +) + +func makeMapStringInterface() reflect.Value { + return reflect.MakeMap(mapStringInterfaceType) +} + +func makeSliceInterface() reflect.Value { + return reflect.MakeSlice(sliceInterfaceType, 0, 16) +} + +func (d *decoder) handleTablePart(key unstable.Iterator, v reflect.Value) (reflect.Value, error) { + return d.handleKeyPart(key, v, d.handleTable, makeMapStringInterface) +} + +func (d *decoder) tryTextUnmarshaler(node *unstable.Node, v reflect.Value) (bool, error) { + // Special case for time, because we allow to unmarshal to it from + // different kind of AST nodes. + if v.Type() == timeType { + return false, nil + } + + if v.CanAddr() && v.Addr().Type().Implements(textUnmarshalerType) { + err := v.Addr().Interface().(encoding.TextUnmarshaler).UnmarshalText(node.Data) + if err != nil { + return false, unstable.NewParserError(d.p.Raw(node.Raw), "%w", err) + } + + return true, nil + } + + return false, nil +} + +func (d *decoder) handleValue(value *unstable.Node, v reflect.Value) error { + for v.Kind() == reflect.Ptr { + v = initAndDereferencePointer(v) + } + + if d.unmarshalerInterface { + if v.CanAddr() && v.Addr().CanInterface() { + if outi, ok := v.Addr().Interface().(unstable.Unmarshaler); ok { + return outi.UnmarshalTOML(value) + } + } + } + + ok, err := d.tryTextUnmarshaler(value, v) + if ok || err != nil { + return err + } + + switch value.Kind { + case unstable.String: + return d.unmarshalString(value, v) + case unstable.Integer: + return d.unmarshalInteger(value, v) + case unstable.Float: + return d.unmarshalFloat(value, v) + case unstable.Bool: + return d.unmarshalBool(value, v) + case unstable.DateTime: + return d.unmarshalDateTime(value, v) + case unstable.LocalDate: + return d.unmarshalLocalDate(value, v) + case unstable.LocalTime: + return d.unmarshalLocalTime(value, v) + case unstable.LocalDateTime: + return d.unmarshalLocalDateTime(value, v) + case unstable.InlineTable: + return d.unmarshalInlineTable(value, v) + case unstable.Array: + return d.unmarshalArray(value, v) + default: + panic(fmt.Errorf("handleValue not implemented for %s", value.Kind)) + } +} + +func (d *decoder) unmarshalArray(array *unstable.Node, v reflect.Value) error { + switch v.Kind() { + case reflect.Slice: + if v.IsNil() { + v.Set(reflect.MakeSlice(v.Type(), 0, 16)) + } else { + v.SetLen(0) + } + case reflect.Array: + // arrays are always initialized + case reflect.Interface: + elem := v.Elem() + if !elem.IsValid() { + elem = reflect.New(sliceInterfaceType).Elem() + elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16)) + } else if elem.Kind() == reflect.Slice { + if elem.Type() != sliceInterfaceType { + elem = reflect.New(sliceInterfaceType).Elem() + elem.Set(reflect.MakeSlice(sliceInterfaceType, 0, 16)) + } else if !elem.CanSet() { + nelem := reflect.New(sliceInterfaceType).Elem() + nelem.Set(reflect.MakeSlice(sliceInterfaceType, elem.Len(), elem.Cap())) + reflect.Copy(nelem, elem) + elem = nelem + } + } + err := d.unmarshalArray(array, elem) + if err != nil { + return err + } + v.Set(elem) + return nil + default: + // TODO: use newDecodeError, but first the parser needs to fill + // array.Data. + return d.typeMismatchError("array", v.Type()) + } + + elemType := v.Type().Elem() + + it := array.Children() + idx := 0 + for it.Next() { + n := it.Node() + + // TODO: optimize + if v.Kind() == reflect.Slice { + elem := reflect.New(elemType).Elem() + + err := d.handleValue(n, elem) + if err != nil { + return err + } + + v.Set(reflect.Append(v, elem)) + } else { // array + if idx >= v.Len() { + return nil + } + elem := v.Index(idx) + err := d.handleValue(n, elem) + if err != nil { + return err + } + idx++ + } + } + + return nil +} + +func (d *decoder) unmarshalInlineTable(itable *unstable.Node, v reflect.Value) error { + // Make sure v is an initialized object. + switch v.Kind() { + case reflect.Map: + if v.IsNil() { + v.Set(reflect.MakeMap(v.Type())) + } + case reflect.Struct: + // structs are always initialized. + case reflect.Interface: + elem := v.Elem() + if !elem.IsValid() { + elem = makeMapStringInterface() + v.Set(elem) + } + return d.unmarshalInlineTable(itable, elem) + default: + return unstable.NewParserError(d.p.Raw(itable.Raw), "cannot store inline table in Go type %s", v.Kind()) + } + + it := itable.Children() + for it.Next() { + n := it.Node() + + x, err := d.handleKeyValue(n, v) + if err != nil { + return err + } + if x.IsValid() { + v = x + } + } + + return nil +} + +func (d *decoder) unmarshalDateTime(value *unstable.Node, v reflect.Value) error { + dt, err := parseDateTime(value.Data) + if err != nil { + return err + } + + v.Set(reflect.ValueOf(dt)) + return nil +} + +func (d *decoder) unmarshalLocalDate(value *unstable.Node, v reflect.Value) error { + ld, err := parseLocalDate(value.Data) + if err != nil { + return err + } + + if v.Type() == timeType { + cast := ld.AsTime(time.Local) + v.Set(reflect.ValueOf(cast)) + return nil + } + + v.Set(reflect.ValueOf(ld)) + + return nil +} + +func (d *decoder) unmarshalLocalTime(value *unstable.Node, v reflect.Value) error { + lt, rest, err := parseLocalTime(value.Data) + if err != nil { + return err + } + + if len(rest) > 0 { + return unstable.NewParserError(rest, "extra characters at the end of a local time") + } + + v.Set(reflect.ValueOf(lt)) + return nil +} + +func (d *decoder) unmarshalLocalDateTime(value *unstable.Node, v reflect.Value) error { + ldt, rest, err := parseLocalDateTime(value.Data) + if err != nil { + return err + } + + if len(rest) > 0 { + return unstable.NewParserError(rest, "extra characters at the end of a local date time") + } + + if v.Type() == timeType { + cast := ldt.AsTime(time.Local) + + v.Set(reflect.ValueOf(cast)) + return nil + } + + v.Set(reflect.ValueOf(ldt)) + + return nil +} + +func (d *decoder) unmarshalBool(value *unstable.Node, v reflect.Value) error { + b := value.Data[0] == 't' + + switch v.Kind() { + case reflect.Bool: + v.SetBool(b) + case reflect.Interface: + v.Set(reflect.ValueOf(b)) + default: + return unstable.NewParserError(value.Data, "cannot assign boolean to a %t", b) + } + + return nil +} + +func (d *decoder) unmarshalFloat(value *unstable.Node, v reflect.Value) error { + f, err := parseFloat(value.Data) + if err != nil { + return err + } + + switch v.Kind() { + case reflect.Float64: + v.SetFloat(f) + case reflect.Float32: + if f > math.MaxFloat32 { + return unstable.NewParserError(value.Data, "number %f does not fit in a float32", f) + } + v.SetFloat(f) + case reflect.Interface: + v.Set(reflect.ValueOf(f)) + default: + return unstable.NewParserError(value.Data, "float cannot be assigned to %s", v.Kind()) + } + + return nil +} + +const ( + maxInt = int64(^uint(0) >> 1) + minInt = -maxInt - 1 +) + +// Maximum value of uint for decoding. Currently the decoder parses the integer +// into an int64. As a result, on architectures where uint is 64 bits, the +// effective maximum uint we can decode is the maximum of int64. On +// architectures where uint is 32 bits, the maximum value we can decode is +// lower: the maximum of uint32. I didn't find a way to figure out this value at +// compile time, so it is computed during initialization. +var maxUint int64 = math.MaxInt64 + +func init() { + m := uint64(^uint(0)) + if m < uint64(maxUint) { + maxUint = int64(m) + } +} + +func (d *decoder) unmarshalInteger(value *unstable.Node, v reflect.Value) error { + kind := v.Kind() + if kind == reflect.Float32 || kind == reflect.Float64 { + return d.unmarshalFloat(value, v) + } + + i, err := parseInteger(value.Data) + if err != nil { + return err + } + + var r reflect.Value + + switch kind { + case reflect.Int64: + v.SetInt(i) + return nil + case reflect.Int32: + if i < math.MinInt32 || i > math.MaxInt32 { + return fmt.Errorf("toml: number %d does not fit in an int32", i) + } + + r = reflect.ValueOf(int32(i)) + case reflect.Int16: + if i < math.MinInt16 || i > math.MaxInt16 { + return fmt.Errorf("toml: number %d does not fit in an int16", i) + } + + r = reflect.ValueOf(int16(i)) + case reflect.Int8: + if i < math.MinInt8 || i > math.MaxInt8 { + return fmt.Errorf("toml: number %d does not fit in an int8", i) + } + + r = reflect.ValueOf(int8(i)) + case reflect.Int: + if i < minInt || i > maxInt { + return fmt.Errorf("toml: number %d does not fit in an int", i) + } + + r = reflect.ValueOf(int(i)) + case reflect.Uint64: + if i < 0 { + return fmt.Errorf("toml: negative number %d does not fit in an uint64", i) + } + + r = reflect.ValueOf(uint64(i)) + case reflect.Uint32: + if i < 0 || i > math.MaxUint32 { + return fmt.Errorf("toml: negative number %d does not fit in an uint32", i) + } + + r = reflect.ValueOf(uint32(i)) + case reflect.Uint16: + if i < 0 || i > math.MaxUint16 { + return fmt.Errorf("toml: negative number %d does not fit in an uint16", i) + } + + r = reflect.ValueOf(uint16(i)) + case reflect.Uint8: + if i < 0 || i > math.MaxUint8 { + return fmt.Errorf("toml: negative number %d does not fit in an uint8", i) + } + + r = reflect.ValueOf(uint8(i)) + case reflect.Uint: + if i < 0 || i > maxUint { + return fmt.Errorf("toml: negative number %d does not fit in an uint", i) + } + + r = reflect.ValueOf(uint(i)) + case reflect.Interface: + r = reflect.ValueOf(i) + default: + return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("integer", v.Type())) + } + + if !r.Type().AssignableTo(v.Type()) { + r = r.Convert(v.Type()) + } + + v.Set(r) + + return nil +} + +func (d *decoder) unmarshalString(value *unstable.Node, v reflect.Value) error { + switch v.Kind() { + case reflect.String: + v.SetString(string(value.Data)) + case reflect.Interface: + v.Set(reflect.ValueOf(string(value.Data))) + default: + return unstable.NewParserError(d.p.Raw(value.Raw), d.typeMismatchString("string", v.Type())) + } + + return nil +} + +func (d *decoder) handleKeyValue(expr *unstable.Node, v reflect.Value) (reflect.Value, error) { + d.strict.EnterKeyValue(expr) + + v, err := d.handleKeyValueInner(expr.Key(), expr.Value(), v) + if d.skipUntilTable { + d.strict.MissingField(expr) + d.skipUntilTable = false + } + + d.strict.ExitKeyValue(expr) + + return v, err +} + +func (d *decoder) handleKeyValueInner(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) { + if key.Next() { + // Still scoping the key + return d.handleKeyValuePart(key, value, v) + } + // Done scoping the key. + // v is whatever Go value we need to fill. + return reflect.Value{}, d.handleValue(value, v) +} + +func (d *decoder) keyFromData(keyType reflect.Type, data []byte) (reflect.Value, error) { + switch { + case stringType.AssignableTo(keyType): + return reflect.ValueOf(string(data)), nil + + case stringType.ConvertibleTo(keyType): + return reflect.ValueOf(string(data)).Convert(keyType), nil + + case keyType.Implements(textUnmarshalerType): + mk := reflect.New(keyType.Elem()) + if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { + return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err) + } + return mk, nil + + case reflect.PointerTo(keyType).Implements(textUnmarshalerType): + mk := reflect.New(keyType) + if err := mk.Interface().(encoding.TextUnmarshaler).UnmarshalText(data); err != nil { + return reflect.Value{}, fmt.Errorf("toml: error unmarshalling key type %s from text: %w", stringType, err) + } + return mk.Elem(), nil + + case keyType.Kind() == reflect.Int || keyType.Kind() == reflect.Int8 || keyType.Kind() == reflect.Int16 || keyType.Kind() == reflect.Int32 || keyType.Kind() == reflect.Int64: + key, err := strconv.ParseInt(string(data), 10, 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from integer: %w", stringType, err) + } + return reflect.ValueOf(key).Convert(keyType), nil + case keyType.Kind() == reflect.Uint || keyType.Kind() == reflect.Uint8 || keyType.Kind() == reflect.Uint16 || keyType.Kind() == reflect.Uint32 || keyType.Kind() == reflect.Uint64: + key, err := strconv.ParseUint(string(data), 10, 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from unsigned integer: %w", stringType, err) + } + return reflect.ValueOf(key).Convert(keyType), nil + + case keyType.Kind() == reflect.Float32: + key, err := strconv.ParseFloat(string(data), 32) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err) + } + return reflect.ValueOf(float32(key)), nil + + case keyType.Kind() == reflect.Float64: + key, err := strconv.ParseFloat(string(data), 64) + if err != nil { + return reflect.Value{}, fmt.Errorf("toml: error parsing key of type %s from float: %w", stringType, err) + } + return reflect.ValueOf(float64(key)), nil + } + return reflect.Value{}, fmt.Errorf("toml: cannot convert map key of type %s to expected type %s", stringType, keyType) +} + +func (d *decoder) handleKeyValuePart(key unstable.Iterator, value *unstable.Node, v reflect.Value) (reflect.Value, error) { + // contains the replacement for v + var rv reflect.Value + + // First, dispatch over v to make sure it is a valid object. + // There is no guarantee over what it could be. + switch v.Kind() { + case reflect.Map: + vt := v.Type() + + mk, err := d.keyFromData(vt.Key(), key.Node().Data) + if err != nil { + return reflect.Value{}, err + } + + // If the map does not exist, create it. + if v.IsNil() { + v = reflect.MakeMap(vt) + rv = v + } + + mv := v.MapIndex(mk) + set := false + if !mv.IsValid() || key.IsLast() { + set = true + mv = reflect.New(v.Type().Elem()).Elem() + } + + nv, err := d.handleKeyValueInner(key, value, mv) + if err != nil { + return reflect.Value{}, err + } + if nv.IsValid() { + mv = nv + set = true + } + + if set { + v.SetMapIndex(mk, mv) + } + case reflect.Struct: + path, found := structFieldPath(v, string(key.Node().Data)) + if !found { + d.skipUntilTable = true + break + } + + if d.errorContext == nil { + d.errorContext = new(errorContext) + } + t := v.Type() + d.errorContext.Struct = t + d.errorContext.Field = path + + f := fieldByIndex(v, path) + + if !f.CanAddr() { + // If the field is not addressable, need to take a slower path and + // make a copy of the struct itself to a new location. + nvp := reflect.New(v.Type()) + nvp.Elem().Set(v) + v = nvp.Elem() + _, err := d.handleKeyValuePart(key, value, v) + if err != nil { + return reflect.Value{}, err + } + return nvp.Elem(), nil + } + x, err := d.handleKeyValueInner(key, value, f) + if err != nil { + return reflect.Value{}, err + } + + if x.IsValid() { + f.Set(x) + } + d.errorContext.Struct = nil + d.errorContext.Field = nil + case reflect.Interface: + v = v.Elem() + + // Following encoding/json: decoding an object into an + // interface{}, it needs to always hold a + // map[string]interface{}. This is for the types to be + // consistent whether a previous value was set or not. + if !v.IsValid() || v.Type() != mapStringInterfaceType { + v = makeMapStringInterface() + } + + x, err := d.handleKeyValuePart(key, value, v) + if err != nil { + return reflect.Value{}, err + } + if x.IsValid() { + v = x + } + rv = v + case reflect.Ptr: + elem := v.Elem() + if !elem.IsValid() { + ptr := reflect.New(v.Type().Elem()) + v.Set(ptr) + rv = v + elem = ptr.Elem() + } + + elem2, err := d.handleKeyValuePart(key, value, elem) + if err != nil { + return reflect.Value{}, err + } + if elem2.IsValid() { + elem = elem2 + } + v.Elem().Set(elem) + default: + return reflect.Value{}, fmt.Errorf("unhandled kv part: %s", v.Kind()) + } + + return rv, nil +} + +func initAndDereferencePointer(v reflect.Value) reflect.Value { + var elem reflect.Value + if v.IsNil() { + ptr := reflect.New(v.Type().Elem()) + v.Set(ptr) + } + elem = v.Elem() + return elem +} + +// Same as reflect.Value.FieldByIndex, but creates pointers if needed. +func fieldByIndex(v reflect.Value, path []int) reflect.Value { + for _, x := range path { + v = v.Field(x) + + if v.Kind() == reflect.Ptr { + if v.IsNil() { + v.Set(reflect.New(v.Type().Elem())) + } + v = v.Elem() + } + } + return v +} + +type fieldPathsMap = map[string][]int + +var globalFieldPathsCache atomic.Value // map[danger.TypeID]fieldPathsMap + +func structFieldPath(v reflect.Value, name string) ([]int, bool) { + t := v.Type() + + cache, _ := globalFieldPathsCache.Load().(map[danger.TypeID]fieldPathsMap) + fieldPaths, ok := cache[danger.MakeTypeID(t)] + + if !ok { + fieldPaths = map[string][]int{} + + forEachField(t, nil, func(name string, path []int) { + fieldPaths[name] = path + // extra copy for the case-insensitive match + fieldPaths[strings.ToLower(name)] = path + }) + + newCache := make(map[danger.TypeID]fieldPathsMap, len(cache)+1) + newCache[danger.MakeTypeID(t)] = fieldPaths + for k, v := range cache { + newCache[k] = v + } + globalFieldPathsCache.Store(newCache) + } + + path, ok := fieldPaths[name] + if !ok { + path, ok = fieldPaths[strings.ToLower(name)] + } + return path, ok +} + +func forEachField(t reflect.Type, path []int, do func(name string, path []int)) { + n := t.NumField() + for i := 0; i < n; i++ { + f := t.Field(i) + + if !f.Anonymous && f.PkgPath != "" { + // only consider exported fields. + continue + } + + fieldPath := append(path, i) + fieldPath = fieldPath[:len(fieldPath):len(fieldPath)] + + name := f.Tag.Get("toml") + if name == "-" { + continue + } + + if i := strings.IndexByte(name, ','); i >= 0 { + name = name[:i] + } + + if f.Anonymous && name == "" { + t2 := f.Type + if t2.Kind() == reflect.Ptr { + t2 = t2.Elem() + } + + if t2.Kind() == reflect.Struct { + forEachField(t2, fieldPath, do) + } + continue + } + + if name == "" { + name = f.Name + } + + do(name, fieldPath) + } +} diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go b/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go new file mode 100644 index 0000000000..f526bf2c09 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/ast.go @@ -0,0 +1,136 @@ +package unstable + +import ( + "fmt" + "unsafe" + + "github.com/pelletier/go-toml/v2/internal/danger" +) + +// Iterator over a sequence of nodes. +// +// Starts uninitialized, you need to call Next() first. +// +// For example: +// +// it := n.Children() +// for it.Next() { +// n := it.Node() +// // do something with n +// } +type Iterator struct { + started bool + node *Node +} + +// Next moves the iterator forward and returns true if points to a +// node, false otherwise. +func (c *Iterator) Next() bool { + if !c.started { + c.started = true + } else if c.node.Valid() { + c.node = c.node.Next() + } + return c.node.Valid() +} + +// IsLast returns true if the current node of the iterator is the last +// one. Subsequent calls to Next() will return false. +func (c *Iterator) IsLast() bool { + return c.node.next == 0 +} + +// Node returns a pointer to the node pointed at by the iterator. +func (c *Iterator) Node() *Node { + return c.node +} + +// Node in a TOML expression AST. +// +// Depending on Kind, its sequence of children should be interpreted +// differently. +// +// - Array have one child per element in the array. +// - InlineTable have one child per key-value in the table (each of kind +// InlineTable). +// - KeyValue have at least two children. The first one is the value. The rest +// make a potentially dotted key. +// - Table and ArrayTable's children represent a dotted key (same as +// KeyValue, but without the first node being the value). +// +// When relevant, Raw describes the range of bytes this node is referring to in +// the input document. Use Parser.Raw() to retrieve the actual bytes. +type Node struct { + Kind Kind + Raw Range // Raw bytes from the input. + Data []byte // Node value (either allocated or referencing the input). + + // References to other nodes, as offsets in the backing array + // from this node. References can go backward, so those can be + // negative. + next int // 0 if last element + child int // 0 if no child +} + +// Range of bytes in the document. +type Range struct { + Offset uint32 + Length uint32 +} + +// Next returns a pointer to the next node, or nil if there is no next node. +func (n *Node) Next() *Node { + if n.next == 0 { + return nil + } + ptr := unsafe.Pointer(n) + size := unsafe.Sizeof(Node{}) + return (*Node)(danger.Stride(ptr, size, n.next)) +} + +// Child returns a pointer to the first child node of this node. Other children +// can be accessed calling Next on the first child. Returns an nil if this Node +// has no child. +func (n *Node) Child() *Node { + if n.child == 0 { + return nil + } + ptr := unsafe.Pointer(n) + size := unsafe.Sizeof(Node{}) + return (*Node)(danger.Stride(ptr, size, n.child)) +} + +// Valid returns true if the node's kind is set (not to Invalid). +func (n *Node) Valid() bool { + return n != nil +} + +// Key returns the children nodes making the Key on a supported node. Panics +// otherwise. They are guaranteed to be all be of the Kind Key. A simple key +// would return just one element. +func (n *Node) Key() Iterator { + switch n.Kind { + case KeyValue: + value := n.Child() + if !value.Valid() { + panic(fmt.Errorf("KeyValue should have at least two children")) + } + return Iterator{node: value.Next()} + case Table, ArrayTable: + return Iterator{node: n.Child()} + default: + panic(fmt.Errorf("Key() is not supported on a %s", n.Kind)) + } +} + +// Value returns a pointer to the value node of a KeyValue. +// Guaranteed to be non-nil. Panics if not called on a KeyValue node, +// or if the Children are malformed. +func (n *Node) Value() *Node { + return n.Child() +} + +// Children returns an iterator over a node's children. +func (n *Node) Children() Iterator { + return Iterator{node: n.Child()} +} diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go b/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go new file mode 100644 index 0000000000..9538e30df9 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/builder.go @@ -0,0 +1,71 @@ +package unstable + +// root contains a full AST. +// +// It is immutable once constructed with Builder. +type root struct { + nodes []Node +} + +// Iterator over the top level nodes. +func (r *root) Iterator() Iterator { + it := Iterator{} + if len(r.nodes) > 0 { + it.node = &r.nodes[0] + } + return it +} + +func (r *root) at(idx reference) *Node { + return &r.nodes[idx] +} + +type reference int + +const invalidReference reference = -1 + +func (r reference) Valid() bool { + return r != invalidReference +} + +type builder struct { + tree root + lastIdx int +} + +func (b *builder) Tree() *root { + return &b.tree +} + +func (b *builder) NodeAt(ref reference) *Node { + return b.tree.at(ref) +} + +func (b *builder) Reset() { + b.tree.nodes = b.tree.nodes[:0] + b.lastIdx = 0 +} + +func (b *builder) Push(n Node) reference { + b.lastIdx = len(b.tree.nodes) + b.tree.nodes = append(b.tree.nodes, n) + return reference(b.lastIdx) +} + +func (b *builder) PushAndChain(n Node) reference { + newIdx := len(b.tree.nodes) + b.tree.nodes = append(b.tree.nodes, n) + if b.lastIdx >= 0 { + b.tree.nodes[b.lastIdx].next = newIdx - b.lastIdx + } + b.lastIdx = newIdx + return reference(b.lastIdx) +} + +func (b *builder) AttachChild(parent reference, child reference) { + b.tree.nodes[parent].child = int(child) - int(parent) +} + +func (b *builder) Chain(from reference, to reference) { + b.tree.nodes[from].next = int(to) - int(from) +} diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/doc.go b/vendor/github.com/pelletier/go-toml/v2/unstable/doc.go new file mode 100644 index 0000000000..7ff26c53c7 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/doc.go @@ -0,0 +1,3 @@ +// Package unstable provides APIs that do not meet the backward compatibility +// guarantees yet. +package unstable diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go b/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go new file mode 100644 index 0000000000..ff9df1bef8 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/kind.go @@ -0,0 +1,71 @@ +package unstable + +import "fmt" + +// Kind represents the type of TOML structure contained in a given Node. +type Kind int + +const ( + // Meta + Invalid Kind = iota + Comment + Key + + // Top level structures + Table + ArrayTable + KeyValue + + // Containers values + Array + InlineTable + + // Values + String + Bool + Float + Integer + LocalDate + LocalTime + LocalDateTime + DateTime +) + +// String implementation of fmt.Stringer. +func (k Kind) String() string { + switch k { + case Invalid: + return "Invalid" + case Comment: + return "Comment" + case Key: + return "Key" + case Table: + return "Table" + case ArrayTable: + return "ArrayTable" + case KeyValue: + return "KeyValue" + case Array: + return "Array" + case InlineTable: + return "InlineTable" + case String: + return "String" + case Bool: + return "Bool" + case Float: + return "Float" + case Integer: + return "Integer" + case LocalDate: + return "LocalDate" + case LocalTime: + return "LocalTime" + case LocalDateTime: + return "LocalDateTime" + case DateTime: + return "DateTime" + } + panic(fmt.Errorf("Kind.String() not implemented for '%d'", k)) +} diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go b/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go new file mode 100644 index 0000000000..50358a44ff --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/parser.go @@ -0,0 +1,1245 @@ +package unstable + +import ( + "bytes" + "fmt" + "unicode" + + "github.com/pelletier/go-toml/v2/internal/characters" + "github.com/pelletier/go-toml/v2/internal/danger" +) + +// ParserError describes an error relative to the content of the document. +// +// It cannot outlive the instance of Parser it refers to, and may cause panics +// if the parser is reset. +type ParserError struct { + Highlight []byte + Message string + Key []string // optional +} + +// Error is the implementation of the error interface. +func (e *ParserError) Error() string { + return e.Message +} + +// NewParserError is a convenience function to create a ParserError +// +// Warning: Highlight needs to be a subslice of Parser.data, so only slices +// returned by Parser.Raw are valid candidates. +func NewParserError(highlight []byte, format string, args ...interface{}) error { + return &ParserError{ + Highlight: highlight, + Message: fmt.Errorf(format, args...).Error(), + } +} + +// Parser scans over a TOML-encoded document and generates an iterative AST. +// +// To prime the Parser, first reset it with the contents of a TOML document. +// Then, process all top-level expressions sequentially. See Example. +// +// Don't forget to check Error() after you're done parsing. +// +// Each top-level expression needs to be fully processed before calling +// NextExpression() again. Otherwise, calls to various Node methods may panic if +// the parser has moved on the next expression. +// +// For performance reasons, go-toml doesn't make a copy of the input bytes to +// the parser. Make sure to copy all the bytes you need to outlive the slice +// given to the parser. +type Parser struct { + data []byte + builder builder + ref reference + left []byte + err error + first bool + + KeepComments bool +} + +// Data returns the slice provided to the last call to Reset. +func (p *Parser) Data() []byte { + return p.data +} + +// Range returns a range description that corresponds to a given slice of the +// input. If the argument is not a subslice of the parser input, this function +// panics. +func (p *Parser) Range(b []byte) Range { + return Range{ + Offset: uint32(danger.SubsliceOffset(p.data, b)), + Length: uint32(len(b)), + } +} + +// Raw returns the slice corresponding to the bytes in the given range. +func (p *Parser) Raw(raw Range) []byte { + return p.data[raw.Offset : raw.Offset+raw.Length] +} + +// Reset brings the parser to its initial state for a given input. It wipes an +// reuses internal storage to reduce allocation. +func (p *Parser) Reset(b []byte) { + p.builder.Reset() + p.ref = invalidReference + p.data = b + p.left = b + p.err = nil + p.first = true +} + +// NextExpression parses the next top-level expression. If an expression was +// successfully parsed, it returns true. If the parser is at the end of the +// document or an error occurred, it returns false. +// +// Retrieve the parsed expression with Expression(). +func (p *Parser) NextExpression() bool { + if len(p.left) == 0 || p.err != nil { + return false + } + + p.builder.Reset() + p.ref = invalidReference + + for { + if len(p.left) == 0 || p.err != nil { + return false + } + + if !p.first { + p.left, p.err = p.parseNewline(p.left) + } + + if len(p.left) == 0 || p.err != nil { + return false + } + + p.ref, p.left, p.err = p.parseExpression(p.left) + + if p.err != nil { + return false + } + + p.first = false + + if p.ref.Valid() { + return true + } + } +} + +// Expression returns a pointer to the node representing the last successfully +// parsed expression. +func (p *Parser) Expression() *Node { + return p.builder.NodeAt(p.ref) +} + +// Error returns any error that has occurred during parsing. +func (p *Parser) Error() error { + return p.err +} + +// Position describes a position in the input. +type Position struct { + // Number of bytes from the beginning of the input. + Offset int + // Line number, starting at 1. + Line int + // Column number, starting at 1. + Column int +} + +// Shape describes the position of a range in the input. +type Shape struct { + Start Position + End Position +} + +func (p *Parser) position(b []byte) Position { + offset := danger.SubsliceOffset(p.data, b) + + lead := p.data[:offset] + + return Position{ + Offset: offset, + Line: bytes.Count(lead, []byte{'\n'}) + 1, + Column: len(lead) - bytes.LastIndex(lead, []byte{'\n'}), + } +} + +// Shape returns the shape of the given range in the input. Will +// panic if the range is not a subslice of the input. +func (p *Parser) Shape(r Range) Shape { + raw := p.Raw(r) + return Shape{ + Start: p.position(raw), + End: p.position(raw[r.Length:]), + } +} + +func (p *Parser) parseNewline(b []byte) ([]byte, error) { + if b[0] == '\n' { + return b[1:], nil + } + + if b[0] == '\r' { + _, rest, err := scanWindowsNewline(b) + return rest, err + } + + return nil, NewParserError(b[0:1], "expected newline but got %#U", b[0]) +} + +func (p *Parser) parseComment(b []byte) (reference, []byte, error) { + ref := invalidReference + data, rest, err := scanComment(b) + if p.KeepComments && err == nil { + ref = p.builder.Push(Node{ + Kind: Comment, + Raw: p.Range(data), + Data: data, + }) + } + return ref, rest, err +} + +func (p *Parser) parseExpression(b []byte) (reference, []byte, error) { + // expression = ws [ comment ] + // expression =/ ws keyval ws [ comment ] + // expression =/ ws table ws [ comment ] + ref := invalidReference + + b = p.parseWhitespace(b) + + if len(b) == 0 { + return ref, b, nil + } + + if b[0] == '#' { + ref, rest, err := p.parseComment(b) + return ref, rest, err + } + + if b[0] == '\n' || b[0] == '\r' { + return ref, b, nil + } + + var err error + if b[0] == '[' { + ref, b, err = p.parseTable(b) + } else { + ref, b, err = p.parseKeyval(b) + } + + if err != nil { + return ref, nil, err + } + + b = p.parseWhitespace(b) + + if len(b) > 0 && b[0] == '#' { + cref, rest, err := p.parseComment(b) + if cref != invalidReference { + p.builder.Chain(ref, cref) + } + return ref, rest, err + } + + return ref, b, nil +} + +func (p *Parser) parseTable(b []byte) (reference, []byte, error) { + // table = std-table / array-table + if len(b) > 1 && b[1] == '[' { + return p.parseArrayTable(b) + } + + return p.parseStdTable(b) +} + +func (p *Parser) parseArrayTable(b []byte) (reference, []byte, error) { + // array-table = array-table-open key array-table-close + // array-table-open = %x5B.5B ws ; [[ Double left square bracket + // array-table-close = ws %x5D.5D ; ]] Double right square bracket + ref := p.builder.Push(Node{ + Kind: ArrayTable, + }) + + b = b[2:] + b = p.parseWhitespace(b) + + k, b, err := p.parseKey(b) + if err != nil { + return ref, nil, err + } + + p.builder.AttachChild(ref, k) + b = p.parseWhitespace(b) + + b, err = expect(']', b) + if err != nil { + return ref, nil, err + } + + b, err = expect(']', b) + + return ref, b, err +} + +func (p *Parser) parseStdTable(b []byte) (reference, []byte, error) { + // std-table = std-table-open key std-table-close + // std-table-open = %x5B ws ; [ Left square bracket + // std-table-close = ws %x5D ; ] Right square bracket + ref := p.builder.Push(Node{ + Kind: Table, + }) + + b = b[1:] + b = p.parseWhitespace(b) + + key, b, err := p.parseKey(b) + if err != nil { + return ref, nil, err + } + + p.builder.AttachChild(ref, key) + + b = p.parseWhitespace(b) + + b, err = expect(']', b) + + return ref, b, err +} + +func (p *Parser) parseKeyval(b []byte) (reference, []byte, error) { + // keyval = key keyval-sep val + ref := p.builder.Push(Node{ + Kind: KeyValue, + }) + + key, b, err := p.parseKey(b) + if err != nil { + return invalidReference, nil, err + } + + // keyval-sep = ws %x3D ws ; = + + b = p.parseWhitespace(b) + + if len(b) == 0 { + return invalidReference, nil, NewParserError(b, "expected = after a key, but the document ends there") + } + + b, err = expect('=', b) + if err != nil { + return invalidReference, nil, err + } + + b = p.parseWhitespace(b) + + valRef, b, err := p.parseVal(b) + if err != nil { + return ref, b, err + } + + p.builder.Chain(valRef, key) + p.builder.AttachChild(ref, valRef) + + return ref, b, err +} + +//nolint:cyclop,funlen +func (p *Parser) parseVal(b []byte) (reference, []byte, error) { + // val = string / boolean / array / inline-table / date-time / float / integer + ref := invalidReference + + if len(b) == 0 { + return ref, nil, NewParserError(b, "expected value, not eof") + } + + var err error + c := b[0] + + switch c { + case '"': + var raw []byte + var v []byte + if scanFollowsMultilineBasicStringDelimiter(b) { + raw, v, b, err = p.parseMultilineBasicString(b) + } else { + raw, v, b, err = p.parseBasicString(b) + } + + if err == nil { + ref = p.builder.Push(Node{ + Kind: String, + Raw: p.Range(raw), + Data: v, + }) + } + + return ref, b, err + case '\'': + var raw []byte + var v []byte + if scanFollowsMultilineLiteralStringDelimiter(b) { + raw, v, b, err = p.parseMultilineLiteralString(b) + } else { + raw, v, b, err = p.parseLiteralString(b) + } + + if err == nil { + ref = p.builder.Push(Node{ + Kind: String, + Raw: p.Range(raw), + Data: v, + }) + } + + return ref, b, err + case 't': + if !scanFollowsTrue(b) { + return ref, nil, NewParserError(atmost(b, 4), "expected 'true'") + } + + ref = p.builder.Push(Node{ + Kind: Bool, + Data: b[:4], + }) + + return ref, b[4:], nil + case 'f': + if !scanFollowsFalse(b) { + return ref, nil, NewParserError(atmost(b, 5), "expected 'false'") + } + + ref = p.builder.Push(Node{ + Kind: Bool, + Data: b[:5], + }) + + return ref, b[5:], nil + case '[': + return p.parseValArray(b) + case '{': + return p.parseInlineTable(b) + default: + return p.parseIntOrFloatOrDateTime(b) + } +} + +func atmost(b []byte, n int) []byte { + if n >= len(b) { + return b + } + + return b[:n] +} + +func (p *Parser) parseLiteralString(b []byte) ([]byte, []byte, []byte, error) { + v, rest, err := scanLiteralString(b) + if err != nil { + return nil, nil, nil, err + } + + return v, v[1 : len(v)-1], rest, nil +} + +func (p *Parser) parseInlineTable(b []byte) (reference, []byte, error) { + // inline-table = inline-table-open [ inline-table-keyvals ] inline-table-close + // inline-table-open = %x7B ws ; { + // inline-table-close = ws %x7D ; } + // inline-table-sep = ws %x2C ws ; , Comma + // inline-table-keyvals = keyval [ inline-table-sep inline-table-keyvals ] + parent := p.builder.Push(Node{ + Kind: InlineTable, + Raw: p.Range(b[:1]), + }) + + first := true + + var child reference + + b = b[1:] + + var err error + + for len(b) > 0 { + previousB := b + b = p.parseWhitespace(b) + + if len(b) == 0 { + return parent, nil, NewParserError(previousB[:1], "inline table is incomplete") + } + + if b[0] == '}' { + break + } + + if !first { + b, err = expect(',', b) + if err != nil { + return parent, nil, err + } + b = p.parseWhitespace(b) + } + + var kv reference + + kv, b, err = p.parseKeyval(b) + if err != nil { + return parent, nil, err + } + + if first { + p.builder.AttachChild(parent, kv) + } else { + p.builder.Chain(child, kv) + } + child = kv + + first = false + } + + rest, err := expect('}', b) + + return parent, rest, err +} + +//nolint:funlen,cyclop +func (p *Parser) parseValArray(b []byte) (reference, []byte, error) { + // array = array-open [ array-values ] ws-comment-newline array-close + // array-open = %x5B ; [ + // array-close = %x5D ; ] + // array-values = ws-comment-newline val ws-comment-newline array-sep array-values + // array-values =/ ws-comment-newline val ws-comment-newline [ array-sep ] + // array-sep = %x2C ; , Comma + // ws-comment-newline = *( wschar / [ comment ] newline ) + arrayStart := b + b = b[1:] + + parent := p.builder.Push(Node{ + Kind: Array, + }) + + // First indicates whether the parser is looking for the first element + // (non-comment) of the array. + first := true + + lastChild := invalidReference + + addChild := func(valueRef reference) { + if lastChild == invalidReference { + p.builder.AttachChild(parent, valueRef) + } else { + p.builder.Chain(lastChild, valueRef) + } + lastChild = valueRef + } + + var err error + for len(b) > 0 { + cref := invalidReference + cref, b, err = p.parseOptionalWhitespaceCommentNewline(b) + if err != nil { + return parent, nil, err + } + + if cref != invalidReference { + addChild(cref) + } + + if len(b) == 0 { + return parent, nil, NewParserError(arrayStart[:1], "array is incomplete") + } + + if b[0] == ']' { + break + } + + if b[0] == ',' { + if first { + return parent, nil, NewParserError(b[0:1], "array cannot start with comma") + } + b = b[1:] + + cref, b, err = p.parseOptionalWhitespaceCommentNewline(b) + if err != nil { + return parent, nil, err + } + if cref != invalidReference { + addChild(cref) + } + } else if !first { + return parent, nil, NewParserError(b[0:1], "array elements must be separated by commas") + } + + // TOML allows trailing commas in arrays. + if len(b) > 0 && b[0] == ']' { + break + } + + var valueRef reference + valueRef, b, err = p.parseVal(b) + if err != nil { + return parent, nil, err + } + + addChild(valueRef) + + cref, b, err = p.parseOptionalWhitespaceCommentNewline(b) + if err != nil { + return parent, nil, err + } + if cref != invalidReference { + addChild(cref) + } + + first = false + } + + rest, err := expect(']', b) + + return parent, rest, err +} + +func (p *Parser) parseOptionalWhitespaceCommentNewline(b []byte) (reference, []byte, error) { + rootCommentRef := invalidReference + latestCommentRef := invalidReference + + addComment := func(ref reference) { + if rootCommentRef == invalidReference { + rootCommentRef = ref + } else if latestCommentRef == invalidReference { + p.builder.AttachChild(rootCommentRef, ref) + latestCommentRef = ref + } else { + p.builder.Chain(latestCommentRef, ref) + latestCommentRef = ref + } + } + + for len(b) > 0 { + var err error + b = p.parseWhitespace(b) + + if len(b) > 0 && b[0] == '#' { + var ref reference + ref, b, err = p.parseComment(b) + if err != nil { + return invalidReference, nil, err + } + if ref != invalidReference { + addComment(ref) + } + } + + if len(b) == 0 { + break + } + + if b[0] == '\n' || b[0] == '\r' { + b, err = p.parseNewline(b) + if err != nil { + return invalidReference, nil, err + } + } else { + break + } + } + + return rootCommentRef, b, nil +} + +func (p *Parser) parseMultilineLiteralString(b []byte) ([]byte, []byte, []byte, error) { + token, rest, err := scanMultilineLiteralString(b) + if err != nil { + return nil, nil, nil, err + } + + i := 3 + + // skip the immediate new line + if token[i] == '\n' { + i++ + } else if token[i] == '\r' && token[i+1] == '\n' { + i += 2 + } + + return token, token[i : len(token)-3], rest, err +} + +//nolint:funlen,gocognit,cyclop +func (p *Parser) parseMultilineBasicString(b []byte) ([]byte, []byte, []byte, error) { + // ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body + // ml-basic-string-delim + // ml-basic-string-delim = 3quotation-mark + // ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ] + // + // mlb-content = mlb-char / newline / mlb-escaped-nl + // mlb-char = mlb-unescaped / escaped + // mlb-quotes = 1*2quotation-mark + // mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii + // mlb-escaped-nl = escape ws newline *( wschar / newline ) + token, escaped, rest, err := scanMultilineBasicString(b) + if err != nil { + return nil, nil, nil, err + } + + i := 3 + + // skip the immediate new line + if token[i] == '\n' { + i++ + } else if token[i] == '\r' && token[i+1] == '\n' { + i += 2 + } + + // fast path + startIdx := i + endIdx := len(token) - len(`"""`) + + if !escaped { + str := token[startIdx:endIdx] + verr := characters.Utf8TomlValidAlreadyEscaped(str) + if verr.Zero() { + return token, str, rest, nil + } + return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8") + } + + var builder bytes.Buffer + + // The scanner ensures that the token starts and ends with quotes and that + // escapes are balanced. + for i < len(token)-3 { + c := token[i] + + //nolint:nestif + if c == '\\' { + // When the last non-whitespace character on a line is an unescaped \, + // it will be trimmed along with all whitespace (including newlines) up + // to the next non-whitespace character or closing delimiter. + + isLastNonWhitespaceOnLine := false + j := 1 + findEOLLoop: + for ; j < len(token)-3-i; j++ { + switch token[i+j] { + case ' ', '\t': + continue + case '\r': + if token[i+j+1] == '\n' { + continue + } + case '\n': + isLastNonWhitespaceOnLine = true + } + break findEOLLoop + } + if isLastNonWhitespaceOnLine { + i += j + for ; i < len(token)-3; i++ { + c := token[i] + if !(c == '\n' || c == '\r' || c == ' ' || c == '\t') { + i-- + break + } + } + i++ + continue + } + + // handle escaping + i++ + c = token[i] + + switch c { + case '"', '\\': + builder.WriteByte(c) + case 'b': + builder.WriteByte('\b') + case 'f': + builder.WriteByte('\f') + case 'n': + builder.WriteByte('\n') + case 'r': + builder.WriteByte('\r') + case 't': + builder.WriteByte('\t') + case 'e': + builder.WriteByte(0x1B) + case 'u': + x, err := hexToRune(atmost(token[i+1:], 4), 4) + if err != nil { + return nil, nil, nil, err + } + builder.WriteRune(x) + i += 4 + case 'U': + x, err := hexToRune(atmost(token[i+1:], 8), 8) + if err != nil { + return nil, nil, nil, err + } + + builder.WriteRune(x) + i += 8 + default: + return nil, nil, nil, NewParserError(token[i:i+1], "invalid escaped character %#U", c) + } + i++ + } else { + size := characters.Utf8ValidNext(token[i:]) + if size == 0 { + return nil, nil, nil, NewParserError(token[i:i+1], "invalid character %#U", c) + } + builder.Write(token[i : i+size]) + i += size + } + } + + return token, builder.Bytes(), rest, nil +} + +func (p *Parser) parseKey(b []byte) (reference, []byte, error) { + // key = simple-key / dotted-key + // simple-key = quoted-key / unquoted-key + // + // unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ + // quoted-key = basic-string / literal-string + // dotted-key = simple-key 1*( dot-sep simple-key ) + // + // dot-sep = ws %x2E ws ; . Period + raw, key, b, err := p.parseSimpleKey(b) + if err != nil { + return invalidReference, nil, err + } + + ref := p.builder.Push(Node{ + Kind: Key, + Raw: p.Range(raw), + Data: key, + }) + + for { + b = p.parseWhitespace(b) + if len(b) > 0 && b[0] == '.' { + b = p.parseWhitespace(b[1:]) + + raw, key, b, err = p.parseSimpleKey(b) + if err != nil { + return ref, nil, err + } + + p.builder.PushAndChain(Node{ + Kind: Key, + Raw: p.Range(raw), + Data: key, + }) + } else { + break + } + } + + return ref, b, nil +} + +func (p *Parser) parseSimpleKey(b []byte) (raw, key, rest []byte, err error) { + if len(b) == 0 { + return nil, nil, nil, NewParserError(b, "expected key but found none") + } + + // simple-key = quoted-key / unquoted-key + // unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ + // quoted-key = basic-string / literal-string + switch { + case b[0] == '\'': + return p.parseLiteralString(b) + case b[0] == '"': + return p.parseBasicString(b) + case isUnquotedKeyChar(b[0]): + key, rest = scanUnquotedKey(b) + return key, key, rest, nil + default: + return nil, nil, nil, NewParserError(b[0:1], "invalid character at start of key: %c", b[0]) + } +} + +//nolint:funlen,cyclop +func (p *Parser) parseBasicString(b []byte) ([]byte, []byte, []byte, error) { + // basic-string = quotation-mark *basic-char quotation-mark + // quotation-mark = %x22 ; " + // basic-char = basic-unescaped / escaped + // basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii + // escaped = escape escape-seq-char + // escape-seq-char = %x22 ; " quotation mark U+0022 + // escape-seq-char =/ %x5C ; \ reverse solidus U+005C + // escape-seq-char =/ %x62 ; b backspace U+0008 + // escape-seq-char =/ %x66 ; f form feed U+000C + // escape-seq-char =/ %x6E ; n line feed U+000A + // escape-seq-char =/ %x72 ; r carriage return U+000D + // escape-seq-char =/ %x74 ; t tab U+0009 + // escape-seq-char =/ %x75 4HEXDIG ; uXXXX U+XXXX + // escape-seq-char =/ %x55 8HEXDIG ; UXXXXXXXX U+XXXXXXXX + token, escaped, rest, err := scanBasicString(b) + if err != nil { + return nil, nil, nil, err + } + + startIdx := len(`"`) + endIdx := len(token) - len(`"`) + + // Fast path. If there is no escape sequence, the string should just be + // an UTF-8 encoded string, which is the same as Go. In that case, + // validate the string and return a direct reference to the buffer. + if !escaped { + str := token[startIdx:endIdx] + verr := characters.Utf8TomlValidAlreadyEscaped(str) + if verr.Zero() { + return token, str, rest, nil + } + return nil, nil, nil, NewParserError(str[verr.Index:verr.Index+verr.Size], "invalid UTF-8") + } + + i := startIdx + + var builder bytes.Buffer + + // The scanner ensures that the token starts and ends with quotes and that + // escapes are balanced. + for i < len(token)-1 { + c := token[i] + if c == '\\' { + i++ + c = token[i] + + switch c { + case '"', '\\': + builder.WriteByte(c) + case 'b': + builder.WriteByte('\b') + case 'f': + builder.WriteByte('\f') + case 'n': + builder.WriteByte('\n') + case 'r': + builder.WriteByte('\r') + case 't': + builder.WriteByte('\t') + case 'e': + builder.WriteByte(0x1B) + case 'u': + x, err := hexToRune(token[i+1:len(token)-1], 4) + if err != nil { + return nil, nil, nil, err + } + + builder.WriteRune(x) + i += 4 + case 'U': + x, err := hexToRune(token[i+1:len(token)-1], 8) + if err != nil { + return nil, nil, nil, err + } + + builder.WriteRune(x) + i += 8 + default: + return nil, nil, nil, NewParserError(token[i:i+1], "invalid escaped character %#U", c) + } + i++ + } else { + size := characters.Utf8ValidNext(token[i:]) + if size == 0 { + return nil, nil, nil, NewParserError(token[i:i+1], "invalid character %#U", c) + } + builder.Write(token[i : i+size]) + i += size + } + } + + return token, builder.Bytes(), rest, nil +} + +func hexToRune(b []byte, length int) (rune, error) { + if len(b) < length { + return -1, NewParserError(b, "unicode point needs %d character, not %d", length, len(b)) + } + b = b[:length] + + var r uint32 + for i, c := range b { + d := uint32(0) + switch { + case '0' <= c && c <= '9': + d = uint32(c - '0') + case 'a' <= c && c <= 'f': + d = uint32(c - 'a' + 10) + case 'A' <= c && c <= 'F': + d = uint32(c - 'A' + 10) + default: + return -1, NewParserError(b[i:i+1], "non-hex character") + } + r = r*16 + d + } + + if r > unicode.MaxRune || 0xD800 <= r && r < 0xE000 { + return -1, NewParserError(b, "escape sequence is invalid Unicode code point") + } + + return rune(r), nil +} + +func (p *Parser) parseWhitespace(b []byte) []byte { + // ws = *wschar + // wschar = %x20 ; Space + // wschar =/ %x09 ; Horizontal tab + _, rest := scanWhitespace(b) + + return rest +} + +//nolint:cyclop +func (p *Parser) parseIntOrFloatOrDateTime(b []byte) (reference, []byte, error) { + switch b[0] { + case 'i': + if !scanFollowsInf(b) { + return invalidReference, nil, NewParserError(atmost(b, 3), "expected 'inf'") + } + + return p.builder.Push(Node{ + Kind: Float, + Data: b[:3], + Raw: p.Range(b[:3]), + }), b[3:], nil + case 'n': + if !scanFollowsNan(b) { + return invalidReference, nil, NewParserError(atmost(b, 3), "expected 'nan'") + } + + return p.builder.Push(Node{ + Kind: Float, + Data: b[:3], + Raw: p.Range(b[:3]), + }), b[3:], nil + case '+', '-': + return p.scanIntOrFloat(b) + } + + if len(b) < 3 { + return p.scanIntOrFloat(b) + } + + s := 5 + if len(b) < s { + s = len(b) + } + + for idx, c := range b[:s] { + if isDigit(c) { + continue + } + + if idx == 2 && c == ':' || (idx == 4 && c == '-') { + return p.scanDateTime(b) + } + + break + } + + return p.scanIntOrFloat(b) +} + +func (p *Parser) scanDateTime(b []byte) (reference, []byte, error) { + // scans for contiguous characters in [0-9T:Z.+-], and up to one space if + // followed by a digit. + hasDate := false + hasTime := false + hasTz := false + seenSpace := false + + i := 0 +byteLoop: + for ; i < len(b); i++ { + c := b[i] + + switch { + case isDigit(c): + case c == '-': + hasDate = true + const minOffsetOfTz = 8 + if i >= minOffsetOfTz { + hasTz = true + } + case c == 'T' || c == 't' || c == ':' || c == '.': + hasTime = true + case c == '+' || c == '-' || c == 'Z' || c == 'z': + hasTz = true + case c == ' ': + if !seenSpace && i+1 < len(b) && isDigit(b[i+1]) { + i += 2 + // Avoid reaching past the end of the document in case the time + // is malformed. See TestIssue585. + if i >= len(b) { + i-- + } + seenSpace = true + hasTime = true + } else { + break byteLoop + } + default: + break byteLoop + } + } + + var kind Kind + + if hasTime { + if hasDate { + if hasTz { + kind = DateTime + } else { + kind = LocalDateTime + } + } else { + kind = LocalTime + } + } else { + kind = LocalDate + } + + return p.builder.Push(Node{ + Kind: kind, + Data: b[:i], + }), b[i:], nil +} + +//nolint:funlen,gocognit,cyclop +func (p *Parser) scanIntOrFloat(b []byte) (reference, []byte, error) { + i := 0 + + if len(b) > 2 && b[0] == '0' && b[1] != '.' && b[1] != 'e' && b[1] != 'E' { + var isValidRune validRuneFn + + switch b[1] { + case 'x': + isValidRune = isValidHexRune + case 'o': + isValidRune = isValidOctalRune + case 'b': + isValidRune = isValidBinaryRune + default: + i++ + } + + if isValidRune != nil { + i += 2 + for ; i < len(b); i++ { + if !isValidRune(b[i]) { + break + } + } + } + + return p.builder.Push(Node{ + Kind: Integer, + Data: b[:i], + Raw: p.Range(b[:i]), + }), b[i:], nil + } + + isFloat := false + + for ; i < len(b); i++ { + c := b[i] + + if c >= '0' && c <= '9' || c == '+' || c == '-' || c == '_' { + continue + } + + if c == '.' || c == 'e' || c == 'E' { + isFloat = true + + continue + } + + if c == 'i' { + if scanFollowsInf(b[i:]) { + return p.builder.Push(Node{ + Kind: Float, + Data: b[:i+3], + Raw: p.Range(b[:i+3]), + }), b[i+3:], nil + } + + return invalidReference, nil, NewParserError(b[i:i+1], "unexpected character 'i' while scanning for a number") + } + + if c == 'n' { + if scanFollowsNan(b[i:]) { + return p.builder.Push(Node{ + Kind: Float, + Data: b[:i+3], + Raw: p.Range(b[:i+3]), + }), b[i+3:], nil + } + + return invalidReference, nil, NewParserError(b[i:i+1], "unexpected character 'n' while scanning for a number") + } + + break + } + + if i == 0 { + return invalidReference, b, NewParserError(b, "incomplete number") + } + + kind := Integer + + if isFloat { + kind = Float + } + + return p.builder.Push(Node{ + Kind: kind, + Data: b[:i], + Raw: p.Range(b[:i]), + }), b[i:], nil +} + +func isDigit(r byte) bool { + return r >= '0' && r <= '9' +} + +type validRuneFn func(r byte) bool + +func isValidHexRune(r byte) bool { + return r >= 'a' && r <= 'f' || + r >= 'A' && r <= 'F' || + r >= '0' && r <= '9' || + r == '_' +} + +func isValidOctalRune(r byte) bool { + return r >= '0' && r <= '7' || r == '_' +} + +func isValidBinaryRune(r byte) bool { + return r == '0' || r == '1' || r == '_' +} + +func expect(x byte, b []byte) ([]byte, error) { + if len(b) == 0 { + return nil, NewParserError(b, "expected character %c but the document ended here", x) + } + + if b[0] != x { + return nil, NewParserError(b[0:1], "expected character %c", x) + } + + return b[1:], nil +} diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go b/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go new file mode 100644 index 0000000000..0512181d28 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/scanner.go @@ -0,0 +1,270 @@ +package unstable + +import "github.com/pelletier/go-toml/v2/internal/characters" + +func scanFollows(b []byte, pattern string) bool { + n := len(pattern) + + return len(b) >= n && string(b[:n]) == pattern +} + +func scanFollowsMultilineBasicStringDelimiter(b []byte) bool { + return scanFollows(b, `"""`) +} + +func scanFollowsMultilineLiteralStringDelimiter(b []byte) bool { + return scanFollows(b, `'''`) +} + +func scanFollowsTrue(b []byte) bool { + return scanFollows(b, `true`) +} + +func scanFollowsFalse(b []byte) bool { + return scanFollows(b, `false`) +} + +func scanFollowsInf(b []byte) bool { + return scanFollows(b, `inf`) +} + +func scanFollowsNan(b []byte) bool { + return scanFollows(b, `nan`) +} + +func scanUnquotedKey(b []byte) ([]byte, []byte) { + // unquoted-key = 1*( ALPHA / DIGIT / %x2D / %x5F ) ; A-Z / a-z / 0-9 / - / _ + for i := 0; i < len(b); i++ { + if !isUnquotedKeyChar(b[i]) { + return b[:i], b[i:] + } + } + + return b, b[len(b):] +} + +func isUnquotedKeyChar(r byte) bool { + return (r >= 'A' && r <= 'Z') || (r >= 'a' && r <= 'z') || (r >= '0' && r <= '9') || r == '-' || r == '_' +} + +func scanLiteralString(b []byte) ([]byte, []byte, error) { + // literal-string = apostrophe *literal-char apostrophe + // apostrophe = %x27 ; ' apostrophe + // literal-char = %x09 / %x20-26 / %x28-7E / non-ascii + for i := 1; i < len(b); { + switch b[i] { + case '\'': + return b[:i+1], b[i+1:], nil + case '\n', '\r': + return nil, nil, NewParserError(b[i:i+1], "literal strings cannot have new lines") + } + size := characters.Utf8ValidNext(b[i:]) + if size == 0 { + return nil, nil, NewParserError(b[i:i+1], "invalid character") + } + i += size + } + + return nil, nil, NewParserError(b[len(b):], "unterminated literal string") +} + +func scanMultilineLiteralString(b []byte) ([]byte, []byte, error) { + // ml-literal-string = ml-literal-string-delim [ newline ] ml-literal-body + // ml-literal-string-delim + // ml-literal-string-delim = 3apostrophe + // ml-literal-body = *mll-content *( mll-quotes 1*mll-content ) [ mll-quotes ] + // + // mll-content = mll-char / newline + // mll-char = %x09 / %x20-26 / %x28-7E / non-ascii + // mll-quotes = 1*2apostrophe + for i := 3; i < len(b); { + switch b[i] { + case '\'': + if scanFollowsMultilineLiteralStringDelimiter(b[i:]) { + i += 3 + + // At that point we found 3 apostrophe, and i is the + // index of the byte after the third one. The scanner + // needs to be eager, because there can be an extra 2 + // apostrophe that can be accepted at the end of the + // string. + + if i >= len(b) || b[i] != '\'' { + return b[:i], b[i:], nil + } + i++ + + if i >= len(b) || b[i] != '\'' { + return b[:i], b[i:], nil + } + i++ + + if i < len(b) && b[i] == '\'' { + return nil, nil, NewParserError(b[i-3:i+1], "''' not allowed in multiline literal string") + } + + return b[:i], b[i:], nil + } + case '\r': + if len(b) < i+2 { + return nil, nil, NewParserError(b[len(b):], `need a \n after \r`) + } + if b[i+1] != '\n' { + return nil, nil, NewParserError(b[i:i+2], `need a \n after \r`) + } + i += 2 // skip the \n + continue + } + size := characters.Utf8ValidNext(b[i:]) + if size == 0 { + return nil, nil, NewParserError(b[i:i+1], "invalid character") + } + i += size + } + + return nil, nil, NewParserError(b[len(b):], `multiline literal string not terminated by '''`) +} + +func scanWindowsNewline(b []byte) ([]byte, []byte, error) { + const lenCRLF = 2 + if len(b) < lenCRLF { + return nil, nil, NewParserError(b, "windows new line expected") + } + + if b[1] != '\n' { + return nil, nil, NewParserError(b, `windows new line should be \r\n`) + } + + return b[:lenCRLF], b[lenCRLF:], nil +} + +func scanWhitespace(b []byte) ([]byte, []byte) { + for i := 0; i < len(b); i++ { + switch b[i] { + case ' ', '\t': + continue + default: + return b[:i], b[i:] + } + } + + return b, b[len(b):] +} + +func scanComment(b []byte) ([]byte, []byte, error) { + // comment-start-symbol = %x23 ; # + // non-ascii = %x80-D7FF / %xE000-10FFFF + // non-eol = %x09 / %x20-7F / non-ascii + // + // comment = comment-start-symbol *non-eol + + for i := 1; i < len(b); { + if b[i] == '\n' { + return b[:i], b[i:], nil + } + if b[i] == '\r' { + if i+1 < len(b) && b[i+1] == '\n' { + return b[:i+1], b[i+1:], nil + } + return nil, nil, NewParserError(b[i:i+1], "invalid character in comment") + } + size := characters.Utf8ValidNext(b[i:]) + if size == 0 { + return nil, nil, NewParserError(b[i:i+1], "invalid character in comment") + } + + i += size + } + + return b, b[len(b):], nil +} + +func scanBasicString(b []byte) ([]byte, bool, []byte, error) { + // basic-string = quotation-mark *basic-char quotation-mark + // quotation-mark = %x22 ; " + // basic-char = basic-unescaped / escaped + // basic-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii + // escaped = escape escape-seq-char + escaped := false + i := 1 + + for ; i < len(b); i++ { + switch b[i] { + case '"': + return b[:i+1], escaped, b[i+1:], nil + case '\n', '\r': + return nil, escaped, nil, NewParserError(b[i:i+1], "basic strings cannot have new lines") + case '\\': + if len(b) < i+2 { + return nil, escaped, nil, NewParserError(b[i:i+1], "need a character after \\") + } + escaped = true + i++ // skip the next character + } + } + + return nil, escaped, nil, NewParserError(b[len(b):], `basic string not terminated by "`) +} + +func scanMultilineBasicString(b []byte) ([]byte, bool, []byte, error) { + // ml-basic-string = ml-basic-string-delim [ newline ] ml-basic-body + // ml-basic-string-delim + // ml-basic-string-delim = 3quotation-mark + // ml-basic-body = *mlb-content *( mlb-quotes 1*mlb-content ) [ mlb-quotes ] + // + // mlb-content = mlb-char / newline / mlb-escaped-nl + // mlb-char = mlb-unescaped / escaped + // mlb-quotes = 1*2quotation-mark + // mlb-unescaped = wschar / %x21 / %x23-5B / %x5D-7E / non-ascii + // mlb-escaped-nl = escape ws newline *( wschar / newline ) + + escaped := false + i := 3 + + for ; i < len(b); i++ { + switch b[i] { + case '"': + if scanFollowsMultilineBasicStringDelimiter(b[i:]) { + i += 3 + + // At that point we found 3 apostrophe, and i is the + // index of the byte after the third one. The scanner + // needs to be eager, because there can be an extra 2 + // apostrophe that can be accepted at the end of the + // string. + + if i >= len(b) || b[i] != '"' { + return b[:i], escaped, b[i:], nil + } + i++ + + if i >= len(b) || b[i] != '"' { + return b[:i], escaped, b[i:], nil + } + i++ + + if i < len(b) && b[i] == '"' { + return nil, escaped, nil, NewParserError(b[i-3:i+1], `""" not allowed in multiline basic string`) + } + + return b[:i], escaped, b[i:], nil + } + case '\\': + if len(b) < i+2 { + return nil, escaped, nil, NewParserError(b[len(b):], "need a character after \\") + } + escaped = true + i++ // skip the next character + case '\r': + if len(b) < i+2 { + return nil, escaped, nil, NewParserError(b[len(b):], `need a \n after \r`) + } + if b[i+1] != '\n' { + return nil, escaped, nil, NewParserError(b[i:i+2], `need a \n after \r`) + } + i++ // skip the \n + } + } + + return nil, escaped, nil, NewParserError(b[len(b):], `multiline basic string not terminated by """`) +} diff --git a/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go b/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go new file mode 100644 index 0000000000..00cfd6de45 --- /dev/null +++ b/vendor/github.com/pelletier/go-toml/v2/unstable/unmarshaler.go @@ -0,0 +1,7 @@ +package unstable + +// The Unmarshaler interface may be implemented by types to customize their +// behavior when being unmarshaled from a TOML document. +type Unmarshaler interface { + UnmarshalTOML(value *Node) error +} diff --git a/vendor/github.com/tonistiigi/fsutil/Dockerfile b/vendor/github.com/tonistiigi/fsutil/Dockerfile index 3a76d341fb..3501573d6d 100644 --- a/vendor/github.com/tonistiigi/fsutil/Dockerfile +++ b/vendor/github.com/tonistiigi/fsutil/Dockerfile @@ -1,7 +1,7 @@ # syntax=docker/dockerfile:1 ARG GO_VERSION=1.23 -ARG XX_VERSION=1.5.0 +ARG XX_VERSION=1.6.1 FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx diff --git a/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl b/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl index 9b30706853..ea73bd2083 100644 --- a/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl +++ b/vendor/github.com/tonistiigi/fsutil/docker-bake.hcl @@ -27,11 +27,18 @@ target "_platforms" { ] } +target "_common" { + args = { + BUILDKIT_CONTEXT_KEEP_GIT_DIR = 1 + } +} + group "default" { targets = ["build"] } target "build" { + inherits = ["_common"] args = { GO_VERSION = "${GO_VERSION}" } @@ -54,6 +61,7 @@ target "test-noroot" { } target "lint" { + inherits = ["_common"] dockerfile = "./hack/dockerfiles/lint.Dockerfile" output = ["type=cacheonly"] args = { @@ -66,6 +74,7 @@ target "lint-cross" { } target "validate-generated-files" { + inherits = ["_common"] dockerfile = "./hack/dockerfiles/generated-files.Dockerfile" output = ["type=cacheonly"] target = "validate" @@ -81,6 +90,7 @@ target "generated-files" { } target "validate-gomod" { + inherits = ["_common"] dockerfile = "./hack/dockerfiles/gomod.Dockerfile" output = ["type=cacheonly"] target = "validate" @@ -99,6 +109,7 @@ target "gomod" { } target "validate-shfmt" { + inherits = ["_common"] dockerfile = "./hack/dockerfiles/shfmt.Dockerfile" output = ["type=cacheonly"] target = "validate" diff --git a/vendor/github.com/tonistiigi/fsutil/filter.go b/vendor/github.com/tonistiigi/fsutil/filter.go index 9cee8ad238..2f0387e12d 100644 --- a/vendor/github.com/tonistiigi/fsutil/filter.go +++ b/vendor/github.com/tonistiigi/fsutil/filter.go @@ -111,7 +111,7 @@ func NewFilterFS(fs FS, opt *FilterOpt) (FS, error) { if len(includePatterns) > 0 { includeMatcher, err = patternmatcher.New(includePatterns) if err != nil { - return nil, errors.Wrapf(err, "invalid includepatterns: %s", opt.IncludePatterns) + return nil, errors.Wrapf(err, "invalid includepatterns: %s", includePatterns) } for _, p := range includeMatcher.Patterns() { diff --git a/vendor/github.com/tonistiigi/go-actions-cache/cache.go b/vendor/github.com/tonistiigi/go-actions-cache/cache.go index 3f29d2f07b..516e719431 100644 --- a/vendor/github.com/tonistiigi/go-actions-cache/cache.go +++ b/vendor/github.com/tonistiigi/go-actions-cache/cache.go @@ -8,7 +8,6 @@ import ( "encoding/json" "fmt" "io" - "io/ioutil" "net/http" "net/url" "os" @@ -219,7 +218,7 @@ func (c *Cache) Load(ctx context.Context, keys ...string) (*Entry, error) { return nil, errors.WithStack(err) } var ce Entry - dt, err := ioutil.ReadAll(io.LimitReader(resp.Body, 32*1024)) + dt, err := io.ReadAll(io.LimitReader(resp.Body, 32*1024)) if err != nil { return nil, errors.WithStack(err) } @@ -252,7 +251,7 @@ func (c *Cache) reserve(ctx context.Context, key string) (int, error) { return 0, errors.WithStack(err) } - dt, err = ioutil.ReadAll(io.LimitReader(resp.Body, 32*1024)) + dt, err = io.ReadAll(io.LimitReader(resp.Body, 32*1024)) if err != nil { return 0, errors.WithStack(err) } @@ -281,7 +280,7 @@ func (c *Cache) commit(ctx context.Context, id int, size int64) error { if err != nil { return errors.Wrapf(err, "error committing cache %d", id) } - dt, err = ioutil.ReadAll(io.LimitReader(resp.Body, 32*1024)) + dt, err = io.ReadAll(io.LimitReader(resp.Body, 32*1024)) if err != nil { return err } @@ -411,7 +410,7 @@ func (c *Cache) uploadChunk(ctx context.Context, id int, ra io.ReaderAt, off, n if err != nil { return errors.WithStack(err) } - dt, err := ioutil.ReadAll(io.LimitReader(resp.Body, 32*1024)) + dt, err := io.ReadAll(io.LimitReader(resp.Body, 32*1024)) if err != nil { return errors.WithStack(err) } @@ -635,7 +634,7 @@ func checkResponse(resp *http.Response) error { if resp.StatusCode >= 200 && resp.StatusCode < 300 { return nil } - dt, err := ioutil.ReadAll(utfbom.SkipOnly(io.LimitReader(resp.Body, 32*1024))) + dt, err := io.ReadAll(utfbom.SkipOnly(io.LimitReader(resp.Body, 32*1024))) if err != nil { return errors.WithStack(err) } diff --git a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go b/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go deleted file mode 100644 index d10ad66533..0000000000 --- a/vendor/google.golang.org/genproto/protobuf/field_mask/field_mask.go +++ /dev/null @@ -1,23 +0,0 @@ -// Copyright 2020 Google LLC -// -// 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 field_mask aliases all exported identifiers in -// package "google.golang.org/protobuf/types/known/fieldmaskpb". -package field_mask - -import "google.golang.org/protobuf/types/known/fieldmaskpb" - -type FieldMask = fieldmaskpb.FieldMask - -var File_google_protobuf_field_mask_proto = fieldmaskpb.File_google_protobuf_field_mask_proto diff --git a/vendor/modules.txt b/vendor/modules.txt index 1b5ea5877d..d4f9b04089 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -76,11 +76,16 @@ github.com/Microsoft/hcsshim/internal/runhcs github.com/Microsoft/hcsshim/internal/safefile github.com/Microsoft/hcsshim/internal/security github.com/Microsoft/hcsshim/internal/timeout +github.com/Microsoft/hcsshim/internal/vhdx github.com/Microsoft/hcsshim/internal/vmcompute github.com/Microsoft/hcsshim/internal/wclayer +github.com/Microsoft/hcsshim/internal/wclayer/cim github.com/Microsoft/hcsshim/internal/winapi github.com/Microsoft/hcsshim/osversion +github.com/Microsoft/hcsshim/pkg/cimfs +github.com/Microsoft/hcsshim/pkg/cimfs/format github.com/Microsoft/hcsshim/pkg/ociwclayer +github.com/Microsoft/hcsshim/pkg/ociwclayer/cim # github.com/RackSec/srslog v0.0.0-20180709174129-a4725f04ec91 ## explicit github.com/RackSec/srslog @@ -258,81 +263,6 @@ github.com/containerd/cgroups/v3/cgroup2/stats # github.com/containerd/console v1.0.4 ## explicit; go 1.13 github.com/containerd/console -# github.com/containerd/containerd v1.7.25 -## explicit; go 1.21 -github.com/containerd/containerd -github.com/containerd/containerd/archive -github.com/containerd/containerd/archive/compression -github.com/containerd/containerd/archive/tarheader -github.com/containerd/containerd/cio -github.com/containerd/containerd/containers -github.com/containerd/containerd/content -github.com/containerd/containerd/content/local -github.com/containerd/containerd/content/proxy -github.com/containerd/containerd/contrib/nvidia -github.com/containerd/containerd/contrib/seccomp/kernelversion -github.com/containerd/containerd/defaults -github.com/containerd/containerd/diff -github.com/containerd/containerd/diff/proxy -github.com/containerd/containerd/diff/walking -github.com/containerd/containerd/errdefs -github.com/containerd/containerd/events -github.com/containerd/containerd/events/exchange -github.com/containerd/containerd/filters -github.com/containerd/containerd/gc -github.com/containerd/containerd/identifiers -github.com/containerd/containerd/images -github.com/containerd/containerd/images/archive -github.com/containerd/containerd/images/converter -github.com/containerd/containerd/labels -github.com/containerd/containerd/leases -github.com/containerd/containerd/leases/proxy -github.com/containerd/containerd/metadata -github.com/containerd/containerd/metadata/boltutil -github.com/containerd/containerd/mount -github.com/containerd/containerd/namespaces -github.com/containerd/containerd/oci -github.com/containerd/containerd/pkg/apparmor -github.com/containerd/containerd/pkg/cap -github.com/containerd/containerd/pkg/cleanup -github.com/containerd/containerd/pkg/deprecation -github.com/containerd/containerd/pkg/dialer -github.com/containerd/containerd/pkg/epoch -github.com/containerd/containerd/pkg/kmutex -github.com/containerd/containerd/pkg/randutil -github.com/containerd/containerd/pkg/runtimeoptions/v1 -github.com/containerd/containerd/pkg/seccomp -github.com/containerd/containerd/pkg/snapshotters -github.com/containerd/containerd/pkg/streaming -github.com/containerd/containerd/pkg/transfer -github.com/containerd/containerd/pkg/transfer/proxy -github.com/containerd/containerd/pkg/transfer/streaming -github.com/containerd/containerd/pkg/unpack -github.com/containerd/containerd/plugin -github.com/containerd/containerd/protobuf -github.com/containerd/containerd/protobuf/proto -github.com/containerd/containerd/protobuf/types -github.com/containerd/containerd/reference -github.com/containerd/containerd/remotes -github.com/containerd/containerd/remotes/docker -github.com/containerd/containerd/remotes/docker/auth -github.com/containerd/containerd/remotes/docker/config -github.com/containerd/containerd/remotes/docker/schema1 -github.com/containerd/containerd/remotes/errors -github.com/containerd/containerd/rootfs -github.com/containerd/containerd/runtime/linux/runctypes -github.com/containerd/containerd/sandbox -github.com/containerd/containerd/sandbox/proxy -github.com/containerd/containerd/services -github.com/containerd/containerd/services/content/contentserver -github.com/containerd/containerd/services/introspection -github.com/containerd/containerd/services/server/config -github.com/containerd/containerd/services/warning -github.com/containerd/containerd/snapshots -github.com/containerd/containerd/snapshots/overlay/overlayutils -github.com/containerd/containerd/snapshots/proxy -github.com/containerd/containerd/tracing -github.com/containerd/containerd/version # github.com/containerd/containerd/api v1.8.0 ## explicit; go 1.21 github.com/containerd/containerd/api/events @@ -353,8 +283,86 @@ github.com/containerd/containerd/api/services/transfer/v1 github.com/containerd/containerd/api/services/version/v1 github.com/containerd/containerd/api/types github.com/containerd/containerd/api/types/runc/options +github.com/containerd/containerd/api/types/runtimeoptions/v1 github.com/containerd/containerd/api/types/task github.com/containerd/containerd/api/types/transfer +# github.com/containerd/containerd/v2 v2.0.2 +## explicit; go 1.22.0 +github.com/containerd/containerd/v2/client +github.com/containerd/containerd/v2/cmd/containerd/server/config +github.com/containerd/containerd/v2/contrib/nvidia +github.com/containerd/containerd/v2/core/containers +github.com/containerd/containerd/v2/core/content +github.com/containerd/containerd/v2/core/content/proxy +github.com/containerd/containerd/v2/core/diff +github.com/containerd/containerd/v2/core/diff/proxy +github.com/containerd/containerd/v2/core/events +github.com/containerd/containerd/v2/core/events/proxy +github.com/containerd/containerd/v2/core/images +github.com/containerd/containerd/v2/core/images/archive +github.com/containerd/containerd/v2/core/images/converter +github.com/containerd/containerd/v2/core/images/usage +github.com/containerd/containerd/v2/core/introspection +github.com/containerd/containerd/v2/core/introspection/proxy +github.com/containerd/containerd/v2/core/leases +github.com/containerd/containerd/v2/core/leases/proxy +github.com/containerd/containerd/v2/core/metadata +github.com/containerd/containerd/v2/core/metadata/boltutil +github.com/containerd/containerd/v2/core/mount +github.com/containerd/containerd/v2/core/remotes +github.com/containerd/containerd/v2/core/remotes/docker +github.com/containerd/containerd/v2/core/remotes/docker/auth +github.com/containerd/containerd/v2/core/remotes/docker/config +github.com/containerd/containerd/v2/core/remotes/docker/schema1 +github.com/containerd/containerd/v2/core/remotes/errors +github.com/containerd/containerd/v2/core/sandbox +github.com/containerd/containerd/v2/core/sandbox/proxy +github.com/containerd/containerd/v2/core/snapshots +github.com/containerd/containerd/v2/core/snapshots/proxy +github.com/containerd/containerd/v2/core/streaming +github.com/containerd/containerd/v2/core/streaming/proxy +github.com/containerd/containerd/v2/core/transfer +github.com/containerd/containerd/v2/core/transfer/proxy +github.com/containerd/containerd/v2/core/transfer/streaming +github.com/containerd/containerd/v2/core/unpack +github.com/containerd/containerd/v2/defaults +github.com/containerd/containerd/v2/internal/cleanup +github.com/containerd/containerd/v2/internal/fsverity +github.com/containerd/containerd/v2/internal/kmutex +github.com/containerd/containerd/v2/internal/randutil +github.com/containerd/containerd/v2/internal/userns +github.com/containerd/containerd/v2/pkg/apparmor +github.com/containerd/containerd/v2/pkg/archive +github.com/containerd/containerd/v2/pkg/archive/compression +github.com/containerd/containerd/v2/pkg/archive/tarheader +github.com/containerd/containerd/v2/pkg/cap +github.com/containerd/containerd/v2/pkg/cio +github.com/containerd/containerd/v2/pkg/deprecation +github.com/containerd/containerd/v2/pkg/dialer +github.com/containerd/containerd/v2/pkg/epoch +github.com/containerd/containerd/v2/pkg/filters +github.com/containerd/containerd/v2/pkg/gc +github.com/containerd/containerd/v2/pkg/identifiers +github.com/containerd/containerd/v2/pkg/kernelversion +github.com/containerd/containerd/v2/pkg/labels +github.com/containerd/containerd/v2/pkg/namespaces +github.com/containerd/containerd/v2/pkg/oci +github.com/containerd/containerd/v2/pkg/protobuf +github.com/containerd/containerd/v2/pkg/protobuf/proto +github.com/containerd/containerd/v2/pkg/protobuf/types +github.com/containerd/containerd/v2/pkg/reference +github.com/containerd/containerd/v2/pkg/rootfs +github.com/containerd/containerd/v2/pkg/seccomp +github.com/containerd/containerd/v2/pkg/snapshotters +github.com/containerd/containerd/v2/pkg/sys +github.com/containerd/containerd/v2/pkg/tracing +github.com/containerd/containerd/v2/plugins +github.com/containerd/containerd/v2/plugins/content/local +github.com/containerd/containerd/v2/plugins/diff/walking +github.com/containerd/containerd/v2/plugins/services +github.com/containerd/containerd/v2/plugins/services/content/contentserver +github.com/containerd/containerd/v2/plugins/snapshots/overlay/overlayutils +github.com/containerd/containerd/v2/version # github.com/containerd/continuity v0.4.5 ## explicit; go 1.21 github.com/containerd/continuity/devices @@ -382,16 +390,19 @@ github.com/containerd/go-runc ## explicit; go 1.20 github.com/containerd/log github.com/containerd/log/logtest -# github.com/containerd/nydus-snapshotter v0.14.0 -## explicit; go 1.21 +# github.com/containerd/nydus-snapshotter v0.15.0 +## explicit; go 1.22.0 github.com/containerd/nydus-snapshotter/pkg/converter github.com/containerd/nydus-snapshotter/pkg/converter/tool github.com/containerd/nydus-snapshotter/pkg/label -# github.com/containerd/platforms v0.2.1 +# github.com/containerd/platforms v1.0.0-rc.1 ## explicit; go 1.20 github.com/containerd/platforms -# github.com/containerd/stargz-snapshotter/estargz v0.15.1 -## explicit; go 1.19 +# github.com/containerd/plugin v1.0.0 +## explicit; go 1.20 +github.com/containerd/plugin +# github.com/containerd/stargz-snapshotter/estargz v0.16.3 +## explicit; go 1.22.0 github.com/containerd/stargz-snapshotter/estargz github.com/containerd/stargz-snapshotter/estargz/errorutil # github.com/containerd/ttrpc v1.2.7 @@ -706,7 +717,7 @@ github.com/mitchellh/hashstructure/v2 # github.com/mitchellh/reflectwalk v1.0.2 ## explicit github.com/mitchellh/reflectwalk -# github.com/moby/buildkit v0.18.2 +# github.com/moby/buildkit v0.19.0-rc2 ## explicit; go 1.22.0 github.com/moby/buildkit/api/services/control github.com/moby/buildkit/api/types @@ -1024,6 +1035,13 @@ github.com/package-url/packageurl-go # github.com/pelletier/go-toml v1.9.5 ## explicit; go 1.12 github.com/pelletier/go-toml +# github.com/pelletier/go-toml/v2 v2.2.3 +## explicit; go 1.21.0 +github.com/pelletier/go-toml/v2 +github.com/pelletier/go-toml/v2/internal/characters +github.com/pelletier/go-toml/v2/internal/danger +github.com/pelletier/go-toml/v2/internal/tracker +github.com/pelletier/go-toml/v2/unstable # github.com/philhofer/fwd v1.1.2 ## explicit; go 1.15 github.com/philhofer/fwd @@ -1107,12 +1125,12 @@ github.com/tinylib/msgp/msgp # github.com/tonistiigi/dchapes-mode v0.0.0-20241001053921-ca0759fec205 ## explicit; go 1.21 github.com/tonistiigi/dchapes-mode -# github.com/tonistiigi/fsutil v0.0.0-20241121093142-31cf1f437184 +# github.com/tonistiigi/fsutil v0.0.0-20250113203817-b14e27f4135a ## explicit; go 1.21 github.com/tonistiigi/fsutil github.com/tonistiigi/fsutil/copy github.com/tonistiigi/fsutil/types -# github.com/tonistiigi/go-actions-cache v0.0.0-20241108014124-394979b8119e +# github.com/tonistiigi/go-actions-cache v0.0.0-20241210095730-017636a73805 ## explicit; go 1.22 github.com/tonistiigi/go-actions-cache # github.com/tonistiigi/go-archvariant v1.0.0 @@ -1443,7 +1461,6 @@ google.golang.org/api/transport/http/internal/propagation # google.golang.org/genproto v0.0.0-20240123012728-ef4313101c80 ## explicit; go 1.19 google.golang.org/genproto/googleapis/logging/type -google.golang.org/genproto/protobuf/field_mask # google.golang.org/genproto/googleapis/api v0.0.0-20241021214115-324edc3d5d38 ## explicit; go 1.21 google.golang.org/genproto/googleapis/api