mirror of
https://github.com/moby/moby.git
synced 2026-01-12 03:01:38 +00:00
Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a21b1a2d12 | ||
|
|
1bc907c97c | ||
|
|
4bb4575ffb | ||
|
|
df7f275db6 | ||
|
|
1c0885d60d | ||
|
|
fb3ec9fc96 | ||
|
|
ed83a9e3a1 | ||
|
|
71b59bf442 | ||
|
|
f8f926b719 | ||
|
|
422ef48c2f | ||
|
|
c9d37a9198 | ||
|
|
1f16a44b3d | ||
|
|
c8f1317585 | ||
|
|
68587c38fe | ||
|
|
d1ea2b1fec | ||
|
|
31c1b7dc17 | ||
|
|
6231ea4a34 | ||
|
|
dc33eb81d8 | ||
|
|
51433d65c0 | ||
|
|
f3bd9da62a | ||
|
|
bc6ae42031 | ||
|
|
af8866f324 | ||
|
|
5e4ddd81a2 | ||
|
|
147eaae6b7 | ||
|
|
c7e4d181a1 | ||
|
|
3d7e824bc2 | ||
|
|
d66b76d2e6 | ||
|
|
0e678a85d7 | ||
|
|
3db1544179 | ||
|
|
03dc388f63 | ||
|
|
5ee23b6050 | ||
|
|
53c521a6b2 | ||
|
|
eccccd7577 | ||
|
|
d9e3d1b815 | ||
|
|
b91e20cc2e | ||
|
|
505be6557b | ||
|
|
b1613dc2a1 | ||
|
|
52f6163746 | ||
|
|
c70e404e9e | ||
|
|
d7a3f01421 | ||
|
|
0f2f9e0049 | ||
|
|
45a1c34202 | ||
|
|
7b31435cf8 | ||
|
|
99df4fee0b | ||
|
|
9f08d1e357 | ||
|
|
73ce798d3b | ||
|
|
b039de78d7 | ||
|
|
7fa33a539a | ||
|
|
7d99ebe418 | ||
|
|
e7e0428218 | ||
|
|
540b29c0c6 | ||
|
|
662f78c0b1 | ||
|
|
b86d9bdaf3 | ||
|
|
0dbc3ac59e | ||
|
|
276a648ec3 | ||
|
|
22aa07b28f | ||
|
|
23b8b023dd | ||
|
|
bf222d635b | ||
|
|
f8231b52d3 | ||
|
|
b951474404 | ||
|
|
c5794e23ec | ||
|
|
02e24483be | ||
|
|
b70040a8fc | ||
|
|
838330bac3 | ||
|
|
e419e22f29 | ||
|
|
e953d76450 | ||
|
|
861fde8cc9 | ||
|
|
3557077867 | ||
|
|
c95b917167 | ||
|
|
c0ff08acbd | ||
|
|
4587688258 |
2
.github/workflows/.test.yml
vendored
2
.github/workflows/.test.yml
vendored
@@ -12,7 +12,7 @@ on:
|
||||
default: "graphdriver"
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.9"
|
||||
GO_VERSION: "1.21.12"
|
||||
GOTESTLIST_VERSION: v0.3.1
|
||||
TESTSTAT_VERSION: v0.1.25
|
||||
ITG_CLI_MATRIX_SIZE: 6
|
||||
|
||||
2
.github/workflows/.windows.yml
vendored
2
.github/workflows/.windows.yml
vendored
@@ -19,7 +19,7 @@ on:
|
||||
default: false
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.11"
|
||||
GO_VERSION: "1.21.12"
|
||||
GOTESTLIST_VERSION: v0.3.1
|
||||
TESTSTAT_VERSION: v0.1.25
|
||||
WINDOWS_BASE_IMAGE: mcr.microsoft.com/windows/servercore
|
||||
|
||||
2
.github/workflows/buildkit.yml
vendored
2
.github/workflows/buildkit.yml
vendored
@@ -13,7 +13,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.11"
|
||||
GO_VERSION: "1.21.12"
|
||||
DESTDIR: ./build
|
||||
SETUP_BUILDX_VERSION: latest
|
||||
SETUP_BUILDKIT_IMAGE: moby/buildkit:latest
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -13,7 +13,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.11"
|
||||
GO_VERSION: "1.21.12"
|
||||
GIT_PAGER: "cat"
|
||||
PAGER: "cat"
|
||||
SETUP_BUILDX_VERSION: latest
|
||||
|
||||
18
.github/workflows/validate-pr.yml
vendored
18
.github/workflows/validate-pr.yml
vendored
@@ -53,10 +53,16 @@ jobs:
|
||||
# Backports or PR that target a release branch directly should mention the target branch in the title, for example:
|
||||
# [X.Y backport] Some change that needs backporting to X.Y
|
||||
# [X.Y] Change directly targeting the X.Y branch
|
||||
- name: Get branch from PR title
|
||||
id: title_branch
|
||||
run: echo "$PR_TITLE" | sed -n 's/^\[\([0-9]*\.[0-9]*\)[^]]*\].*/branch=\1/p' >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Check release branch
|
||||
if: github.event.pull_request.base.ref != steps.title_branch.outputs.branch && !(github.event.pull_request.base.ref == 'master' && steps.title_branch.outputs.branch == '')
|
||||
run: echo "::error::PR title suggests targetting the ${{ steps.title_branch.outputs.branch }} branch, but is opened against ${{ github.event.pull_request.base.ref }}" && exit 1
|
||||
id: title_branch
|
||||
run: |
|
||||
# get the intended major version prefix ("[27.1 backport]" -> "27.") from the PR title.
|
||||
[[ "$PR_TITLE" =~ ^\[([0-9]*\.)[^]]*\] ]] && branch="${BASH_REMATCH[1]}"
|
||||
|
||||
# get major version prefix from the release branch ("27.x -> "27.")
|
||||
[[ "$GITHUB_BASE_REF" =~ ^([0-9]*\.) ]] && target_branch="${BASH_REMATCH[1]}" || target_branch="$GITHUB_BASE_REF"
|
||||
|
||||
if [[ "$target_branch" != "$branch" ]] && ! [[ "$GITHUB_BASE_REF" == "master" && "$branch" == "" ]]; then
|
||||
echo "::error::PR is opened against the $GITHUB_BASE_REF branch, but its title suggests otherwise."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
12
Dockerfile
12
Dockerfile
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
|
||||
ARG GO_VERSION=1.21.11
|
||||
ARG GO_VERSION=1.21.12
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
ARG XX_VERSION=1.4.0
|
||||
@@ -8,12 +8,12 @@ ARG XX_VERSION=1.4.0
|
||||
ARG VPNKIT_VERSION=0.5.0
|
||||
|
||||
ARG DOCKERCLI_REPOSITORY="https://github.com/docker/cli.git"
|
||||
ARG DOCKERCLI_VERSION=v26.1.0
|
||||
ARG DOCKERCLI_VERSION=v27.0.2
|
||||
# cli version used for integration-cli tests
|
||||
ARG DOCKERCLI_INTEGRATION_REPOSITORY="https://github.com/docker/cli.git"
|
||||
ARG DOCKERCLI_INTEGRATION_VERSION=v17.06.2-ce
|
||||
ARG BUILDX_VERSION=0.15.1
|
||||
ARG COMPOSE_VERSION=v2.27.1
|
||||
ARG BUILDX_VERSION=0.16.1
|
||||
ARG COMPOSE_VERSION=v2.29.0
|
||||
|
||||
ARG SYSTEMD="false"
|
||||
ARG DOCKER_STATIC=1
|
||||
@@ -196,7 +196,7 @@ RUN git init . && git remote add origin "https://github.com/containerd/container
|
||||
# When updating the binary version you may also need to update the vendor
|
||||
# version to pick up bug fixes or new APIs, however, usually the Go packages
|
||||
# are built from a commit from the master branch.
|
||||
ARG CONTAINERD_VERSION=v1.7.18
|
||||
ARG CONTAINERD_VERSION=v1.7.20
|
||||
RUN git fetch -q --depth 1 origin "${CONTAINERD_VERSION}" +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD
|
||||
|
||||
FROM base AS containerd-build
|
||||
@@ -229,7 +229,7 @@ FROM binary-dummy AS containerd-windows
|
||||
FROM containerd-${TARGETOS} AS containerd
|
||||
|
||||
FROM base AS golangci_lint
|
||||
ARG GOLANGCI_LINT_VERSION=v1.55.2
|
||||
ARG GOLANGCI_LINT_VERSION=v1.59.1
|
||||
RUN --mount=type=cache,target=/root/.cache/go-build \
|
||||
--mount=type=cache,target=/go/pkg/mod \
|
||||
GOBIN=/build/ GO111MODULE=on go install "github.com/golangci/golangci-lint/cmd/golangci-lint@${GOLANGCI_LINT_VERSION}" \
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# This represents the bare minimum required to build and test Docker.
|
||||
|
||||
ARG GO_VERSION=1.21.11
|
||||
ARG GO_VERSION=1.21.12
|
||||
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
|
||||
@@ -161,10 +161,10 @@ FROM ${WINDOWS_BASE_IMAGE}:${WINDOWS_BASE_IMAGE_TAG}
|
||||
# Use PowerShell as the default shell
|
||||
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
|
||||
|
||||
ARG GO_VERSION=1.21.11
|
||||
ARG GO_VERSION=1.21.12
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG GOWINRES_VERSION=v0.3.1
|
||||
ARG CONTAINERD_VERSION=v1.7.18
|
||||
ARG CONTAINERD_VERSION=v1.7.20
|
||||
|
||||
# Environment variable notes:
|
||||
# - GO_VERSION must be consistent with 'Dockerfile' used by Linux.
|
||||
|
||||
@@ -88,11 +88,9 @@ func (b *Backend) Build(ctx context.Context, config backend.BuildConfig) (string
|
||||
}
|
||||
}
|
||||
|
||||
if !useBuildKit {
|
||||
stdout := config.ProgressWriter.StdoutFormatter
|
||||
fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
|
||||
}
|
||||
if imageID != "" && !useBuildKit {
|
||||
stdout := config.ProgressWriter.StdoutFormatter
|
||||
_, _ = fmt.Fprintf(stdout, "Successfully built %s\n", stringid.TruncateID(imageID))
|
||||
err = tagImages(ctx, b.imageComponent, config.ProgressWriter.StdoutFormatter, image.ID(imageID), tags)
|
||||
}
|
||||
return imageID, err
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"net/url"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/errdefs"
|
||||
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/server/httpstatus"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
"github.com/docker/docker/api/types"
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/server/httputils"
|
||||
|
||||
@@ -53,7 +53,7 @@ func TestAdjustForAPIVersion(t *testing.T) {
|
||||
Target: "/bar",
|
||||
TmpfsOptions: &mount.TmpfsOptions{
|
||||
Options: [][]string{
|
||||
[]string{"exec"},
|
||||
{"exec"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -73,7 +73,7 @@ func TestAdjustForAPIVersion(t *testing.T) {
|
||||
adjustForAPIVersion("1.46", spec)
|
||||
if !reflect.DeepEqual(
|
||||
spec.TaskTemplate.ContainerSpec.Mounts[0].TmpfsOptions.Options,
|
||||
[][]string{[]string{"exec"}},
|
||||
[][]string{{"exec"}},
|
||||
) {
|
||||
t.Error("TmpfsOptions.Options was stripped from spec")
|
||||
}
|
||||
|
||||
@@ -81,7 +81,6 @@ func (s *systemRouter) getInfo(ctx context.Context, w http.ResponseWriter, r *ht
|
||||
nameOnly = append(nameOnly, so.Name)
|
||||
}
|
||||
info.SecurityOptions = nameOnly
|
||||
info.ExecutionDriver = "<not supported>" //nolint:staticcheck // ignore SA1019 (ExecutionDriver is deprecated)
|
||||
}
|
||||
if versions.LessThan(version, "1.39") {
|
||||
if info.KernelVersion == "" {
|
||||
|
||||
@@ -5334,7 +5334,7 @@ definitions:
|
||||
The version Go used to compile the daemon, and the version of the Go
|
||||
runtime in use.
|
||||
type: "string"
|
||||
example: "go1.21.11"
|
||||
example: "go1.21.12"
|
||||
Os:
|
||||
description: |
|
||||
The operating system that the daemon is running on ("linux" or "windows")
|
||||
@@ -9563,7 +9563,7 @@ paths:
|
||||
|
||||
Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `exec_die`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, `update`, and `prune`
|
||||
|
||||
Images report these events: `create, `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, `untag`, and `prune`
|
||||
Images report these events: `create`, `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, `untag`, and `prune`
|
||||
|
||||
Volumes report these events: `create`, `mount`, `unmount`, `destroy`, and `prune`
|
||||
|
||||
|
||||
@@ -77,9 +77,6 @@ type Info struct {
|
||||
|
||||
Containerd *ContainerdInfo `json:",omitempty"`
|
||||
|
||||
// Legacy API fields for older API versions.
|
||||
legacyFields
|
||||
|
||||
// Warnings contains a slice of warnings that occurred while collecting
|
||||
// system information. These warnings are intended to be informational
|
||||
// messages for the user, and are not intended to be parsed / used for
|
||||
@@ -124,10 +121,6 @@ type ContainerdNamespaces struct {
|
||||
Plugins string
|
||||
}
|
||||
|
||||
type legacyFields struct {
|
||||
ExecutionDriver string `json:",omitempty"` // Deprecated: deprecated since API v1.25, but returned for older versions.
|
||||
}
|
||||
|
||||
// PluginsInfo is a temp struct holding Plugins name
|
||||
// registered with docker daemon. It is used by [Info] struct
|
||||
type PluginsInfo struct {
|
||||
|
||||
@@ -245,18 +245,6 @@ type ContainerState struct {
|
||||
Health *Health `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ContainerNode stores information about the node that a container
|
||||
// is running on. It's only used by the Docker Swarm standalone API
|
||||
type ContainerNode struct {
|
||||
ID string
|
||||
IPAddress string `json:"IP"`
|
||||
Addr string
|
||||
Name string
|
||||
Cpus int
|
||||
Memory int64
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
// ContainerJSONBase contains response of Engine API:
|
||||
// GET "/containers/{name:.*}/json"
|
||||
type ContainerJSONBase struct {
|
||||
@@ -270,7 +258,7 @@ type ContainerJSONBase struct {
|
||||
HostnamePath string
|
||||
HostsPath string
|
||||
LogPath string
|
||||
Node *ContainerNode `json:",omitempty"` // Node is only propagated by Docker Swarm standalone API
|
||||
Node *ContainerNode `json:",omitempty"` // Deprecated: Node was only propagated by Docker Swarm standalone API. It sill be removed in the next release.
|
||||
Name string
|
||||
RestartCount int
|
||||
Driver string
|
||||
|
||||
@@ -194,3 +194,17 @@ type ImageImportSource image.ImportSource
|
||||
//
|
||||
// Deprecated: use [image.LoadResponse].
|
||||
type ImageLoadResponse = image.LoadResponse
|
||||
|
||||
// ContainerNode stores information about the node that a container
|
||||
// is running on. It's only used by the Docker Swarm standalone API.
|
||||
//
|
||||
// Deprecated: ContainerNode was used for the classic Docker Swarm standalone API. It will be removed in the next release.
|
||||
type ContainerNode struct {
|
||||
ID string
|
||||
IPAddress string `json:"IP"`
|
||||
Addr string
|
||||
Name string
|
||||
Cpus int
|
||||
Memory int64
|
||||
Labels map[string]string
|
||||
}
|
||||
|
||||
@@ -18,7 +18,6 @@ import (
|
||||
"github.com/containerd/containerd/gc"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
cdreference "github.com/containerd/containerd/reference"
|
||||
ctdreference "github.com/containerd/containerd/reference"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
@@ -26,6 +25,7 @@ import (
|
||||
"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.
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
distreference "github.com/distribution/reference"
|
||||
dimages "github.com/docker/docker/daemon/images"
|
||||
"github.com/docker/docker/distribution/metadata"
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
@@ -77,24 +77,24 @@ var cacheFields = map[string]bool{
|
||||
|
||||
// Opt is option struct required for creating the builder
|
||||
type Opt struct {
|
||||
SessionManager *session.Manager
|
||||
Root string
|
||||
EngineID string
|
||||
Dist images.DistributionServices
|
||||
ImageTagger mobyexporter.ImageTagger
|
||||
NetworkController *libnetwork.Controller
|
||||
DefaultCgroupParent string
|
||||
RegistryHosts docker.RegistryHosts
|
||||
BuilderConfig config.BuilderConfig
|
||||
Rootless bool
|
||||
IdentityMapping idtools.IdentityMapping
|
||||
DNSConfig config.DNSConfig
|
||||
ApparmorProfile string
|
||||
UseSnapshotter bool
|
||||
Snapshotter string
|
||||
ContainerdAddress string
|
||||
ContainerdNamespace string
|
||||
ImageExportedCallback exporter.ImageExportedByBuildkit
|
||||
SessionManager *session.Manager
|
||||
Root string
|
||||
EngineID string
|
||||
Dist images.DistributionServices
|
||||
ImageTagger mobyexporter.ImageTagger
|
||||
NetworkController *libnetwork.Controller
|
||||
DefaultCgroupParent string
|
||||
RegistryHosts docker.RegistryHosts
|
||||
BuilderConfig config.BuilderConfig
|
||||
Rootless bool
|
||||
IdentityMapping idtools.IdentityMapping
|
||||
DNSConfig config.DNSConfig
|
||||
ApparmorProfile string
|
||||
UseSnapshotter bool
|
||||
Snapshotter string
|
||||
ContainerdAddress string
|
||||
ContainerdNamespace string
|
||||
Callbacks exporter.BuildkitCallbacks
|
||||
}
|
||||
|
||||
// Builder can build using BuildKit backend
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
ctd "github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/content/local"
|
||||
ctdmetadata "github.com/containerd/containerd/metadata"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
"github.com/docker/docker/builder/builder-next/adapters/containerimage"
|
||||
@@ -109,11 +109,22 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
|
||||
dns := getDNSConfig(opt.DNSConfig)
|
||||
|
||||
wo, err := containerd.NewWorkerOpt(opt.Root, opt.ContainerdAddress, opt.Snapshotter, opt.ContainerdNamespace,
|
||||
opt.Rootless, map[string]string{
|
||||
workerOpts := containerd.WorkerOptions{
|
||||
Root: opt.Root,
|
||||
Address: opt.ContainerdAddress,
|
||||
SnapshotterName: opt.Snapshotter,
|
||||
Namespace: opt.ContainerdNamespace,
|
||||
Rootless: opt.Rootless,
|
||||
Labels: map[string]string{
|
||||
label.Snapshotter: opt.Snapshotter,
|
||||
}, dns, nc, opt.ApparmorProfile, false, nil, "", nil, ctd.WithTimeout(60*time.Second),
|
||||
)
|
||||
},
|
||||
DNS: dns,
|
||||
NetworkOpt: nc,
|
||||
ApparmorProfile: opt.ApparmorProfile,
|
||||
Selinux: false,
|
||||
}
|
||||
|
||||
wo, err := containerd.NewWorkerOpt(workerOpts, ctd.WithTimeout(60*time.Second))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -138,7 +149,7 @@ func newSnapshotterController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
}
|
||||
wo.Executor = exec
|
||||
|
||||
w, err := mobyworker.NewContainerdWorker(ctx, wo, opt.ImageExportedCallback)
|
||||
w, err := mobyworker.NewContainerdWorker(ctx, wo, opt.Callbacks)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -321,7 +332,8 @@ func newGraphDriverController(ctx context.Context, rt http.RoundTripper, opt Opt
|
||||
Differ: differ,
|
||||
ImageTagger: opt.ImageTagger,
|
||||
LeaseManager: lm,
|
||||
ImageExportedCallback: opt.ImageExportedCallback,
|
||||
ImageExportedCallback: opt.Callbacks.Exported,
|
||||
// Callbacks.Named is not used here because the tag operation is handled directly by the image service.
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/log"
|
||||
distref "github.com/distribution/reference"
|
||||
builderexporter "github.com/docker/docker/builder/builder-next/exporter"
|
||||
"github.com/docker/docker/image"
|
||||
"github.com/docker/docker/layer"
|
||||
"github.com/moby/buildkit/exporter"
|
||||
@@ -38,7 +37,7 @@ type Opt struct {
|
||||
ImageTagger ImageTagger
|
||||
ContentStore content.Store
|
||||
LeaseManager leases.Manager
|
||||
ImageExportedCallback builderexporter.ImageExportedByBuildkit
|
||||
ImageExportedCallback func(ctx context.Context, id string, desc ocispec.Descriptor)
|
||||
}
|
||||
|
||||
type imageExporter struct {
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/moby/buildkit/cache"
|
||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||
"github.com/moby/buildkit/util/progress"
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/builder/builder-next/exporter/overrides"
|
||||
"github.com/moby/buildkit/exporter"
|
||||
"github.com/moby/buildkit/exporter/containerimage/exptypes"
|
||||
@@ -11,19 +13,29 @@ import (
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type ImageExportedByBuildkit = func(ctx context.Context, id string, desc ocispec.Descriptor) error
|
||||
type BuildkitCallbacks struct {
|
||||
// Exported is a Called when an image is exported by buildkit.
|
||||
Exported func(ctx context.Context, id string, desc ocispec.Descriptor)
|
||||
|
||||
// Named is a callback that is called when an image is created in the
|
||||
// containerd image store by buildkit.
|
||||
Named func(ctx context.Context, ref reference.NamedTagged, desc ocispec.Descriptor)
|
||||
}
|
||||
|
||||
// Wraps the containerimage exporter's Resolve method to apply moby-specific
|
||||
// overrides to the exporter attributes.
|
||||
type imageExporterMobyWrapper struct {
|
||||
exp exporter.Exporter
|
||||
callback ImageExportedByBuildkit
|
||||
exp exporter.Exporter
|
||||
callbacks BuildkitCallbacks
|
||||
}
|
||||
|
||||
// NewWrapper returns an exporter wrapper that applies moby specific attributes
|
||||
// and hooks the export process.
|
||||
func NewWrapper(exp exporter.Exporter, callback ImageExportedByBuildkit) (exporter.Exporter, error) {
|
||||
return &imageExporterMobyWrapper{exp: exp, callback: callback}, nil
|
||||
func NewWrapper(exp exporter.Exporter, callbacks BuildkitCallbacks) (exporter.Exporter, error) {
|
||||
return &imageExporterMobyWrapper{
|
||||
exp: exp,
|
||||
callbacks: callbacks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Resolve applies moby specific attributes to the request.
|
||||
@@ -46,12 +58,15 @@ func (e *imageExporterMobyWrapper) Resolve(ctx context.Context, id int, exporter
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &imageExporterInstanceWrapper{ExporterInstance: inst, callback: e.callback}, nil
|
||||
return &imageExporterInstanceWrapper{
|
||||
ExporterInstance: inst,
|
||||
callbacks: e.callbacks,
|
||||
}, nil
|
||||
}
|
||||
|
||||
type imageExporterInstanceWrapper struct {
|
||||
exporter.ExporterInstance
|
||||
callback ImageExportedByBuildkit
|
||||
callbacks BuildkitCallbacks
|
||||
}
|
||||
|
||||
func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter.Source, inlineCache exptypes.InlineCache, sessionID string) (map[string]string, exporter.DescriptorReference, error) {
|
||||
@@ -62,8 +77,26 @@ func (i *imageExporterInstanceWrapper) Export(ctx context.Context, src *exporter
|
||||
|
||||
desc := ref.Descriptor()
|
||||
imageID := out[exptypes.ExporterImageDigestKey]
|
||||
if i.callback != nil {
|
||||
i.callback(ctx, imageID, desc)
|
||||
if i.callbacks.Exported != nil {
|
||||
i.callbacks.Exported(ctx, imageID, desc)
|
||||
}
|
||||
|
||||
if i.callbacks.Named != nil {
|
||||
for _, name := range strings.Split(out[string(exptypes.OptKeyName)], ",") {
|
||||
ref, err := reference.ParseNormalizedNamed(name)
|
||||
if err != nil {
|
||||
// Shouldn't happen, but log if it does and continue.
|
||||
log.G(ctx).WithFields(log.Fields{
|
||||
"name": name,
|
||||
"error": err,
|
||||
}).Warn("image named with invalid reference produced by buildkit")
|
||||
continue
|
||||
}
|
||||
|
||||
namedTagged := reference.TagNameOnly(ref).(reference.NamedTagged)
|
||||
i.callbacks.Named(ctx, namedTagged, desc)
|
||||
}
|
||||
}
|
||||
|
||||
return out, ref, nil
|
||||
}
|
||||
|
||||
@@ -3,9 +3,9 @@ package worker
|
||||
import (
|
||||
"context"
|
||||
|
||||
mobyexporter "github.com/docker/docker/builder/builder-next/exporter"
|
||||
"github.com/docker/docker/builder/builder-next/exporter"
|
||||
"github.com/moby/buildkit/client"
|
||||
"github.com/moby/buildkit/exporter"
|
||||
bkexporter "github.com/moby/buildkit/exporter"
|
||||
"github.com/moby/buildkit/session"
|
||||
"github.com/moby/buildkit/worker/base"
|
||||
)
|
||||
@@ -13,27 +13,27 @@ import (
|
||||
// ContainerdWorker is a local worker instance with dedicated snapshotter, cache, and so on.
|
||||
type ContainerdWorker struct {
|
||||
*base.Worker
|
||||
callback mobyexporter.ImageExportedByBuildkit
|
||||
callbacks exporter.BuildkitCallbacks
|
||||
}
|
||||
|
||||
// NewContainerdWorker instantiates a local worker.
|
||||
func NewContainerdWorker(ctx context.Context, wo base.WorkerOpt, callback mobyexporter.ImageExportedByBuildkit) (*ContainerdWorker, error) {
|
||||
func NewContainerdWorker(ctx context.Context, wo base.WorkerOpt, callbacks exporter.BuildkitCallbacks) (*ContainerdWorker, error) {
|
||||
bw, err := base.NewWorker(ctx, wo)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &ContainerdWorker{Worker: bw, callback: callback}, nil
|
||||
return &ContainerdWorker{Worker: bw, callbacks: callbacks}, nil
|
||||
}
|
||||
|
||||
// Exporter returns exporter by name
|
||||
func (w *ContainerdWorker) Exporter(name string, sm *session.Manager) (exporter.Exporter, error) {
|
||||
func (w *ContainerdWorker) Exporter(name string, sm *session.Manager) (bkexporter.Exporter, error) {
|
||||
switch name {
|
||||
case mobyexporter.Moby:
|
||||
case exporter.Moby:
|
||||
exp, err := w.Worker.Exporter(client.ExporterImage, sm)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return mobyexporter.NewWrapper(exp, w.callback)
|
||||
return exporter.NewWrapper(exp, w.callbacks)
|
||||
default:
|
||||
return w.Worker.Exporter(name, sm)
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/rootfs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
imageadapter "github.com/docker/docker/builder/builder-next/adapters/containerimage"
|
||||
mobyexporter "github.com/docker/docker/builder/builder-next/exporter"
|
||||
distmetadata "github.com/docker/docker/distribution/metadata"
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
@@ -228,7 +228,7 @@ func emitImageID(aux *streamformatter.AuxFormatter, state *dispatchState) error
|
||||
|
||||
func processMetaArg(meta instructions.ArgCommand, shlex *shell.Lex, args *BuildArgs) error {
|
||||
// shell.Lex currently only support the concatenated string format
|
||||
envs := convertMapToEnvList(args.GetAllAllowed())
|
||||
envs := shell.EnvsFromSlice(convertMapToEnvList(args.GetAllAllowed()))
|
||||
if err := meta.Expand(func(word string) (string, error) {
|
||||
newword, _, err := shlex.ProcessWord(word, envs)
|
||||
return newword, err
|
||||
|
||||
@@ -15,7 +15,7 @@ import (
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api"
|
||||
"github.com/docker/docker/api/types/strslice"
|
||||
"github.com/docker/docker/builder"
|
||||
@@ -224,7 +224,7 @@ func (d *dispatchRequest) getExpandedString(shlex *shell.Lex, str string) (strin
|
||||
substitutionArgs = append(substitutionArgs, key+"="+value)
|
||||
}
|
||||
|
||||
name, _, err := shlex.ProcessWord(str, substitutionArgs)
|
||||
name, _, err := shlex.ProcessWord(str, shell.EnvsFromSlice(substitutionArgs))
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
@@ -508,7 +508,7 @@ func dispatchEntrypoint(ctx context.Context, d dispatchRequest, c *instructions.
|
||||
//
|
||||
// Expose ports for links and port mappings. This all ends up in
|
||||
// req.runConfig.ExposedPorts for runconfig.
|
||||
func dispatchExpose(ctx context.Context, d dispatchRequest, c *instructions.ExposeCommand, envs []string) error {
|
||||
func dispatchExpose(ctx context.Context, d dispatchRequest, c *instructions.ExposeCommand, envs shell.EnvGetter) error {
|
||||
// custom multi word expansion
|
||||
// expose $FOO with FOO="80 443" is expanded as EXPOSE [80,443]. This is the only command supporting word to words expansion
|
||||
// so the word processing has been de-generalized
|
||||
|
||||
@@ -43,7 +43,7 @@ func dispatch(ctx context.Context, d dispatchRequest, cmd instructions.Command)
|
||||
}
|
||||
}
|
||||
runConfigEnv := d.state.runConfig.Env
|
||||
envs := append(runConfigEnv, d.state.buildArgs.FilterAllowed(runConfigEnv)...)
|
||||
envs := shell.EnvsFromSlice(append(runConfigEnv, d.state.buildArgs.FilterAllowed(runConfigEnv)...))
|
||||
|
||||
if ex, ok := cmd.(instructions.SupportsSingleWordExpansion); ok {
|
||||
err := ex.Expand(func(word string) (string, error) {
|
||||
|
||||
@@ -4,8 +4,8 @@ import (
|
||||
"context"
|
||||
"runtime"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/builder"
|
||||
dockerimage "github.com/docker/docker/image"
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"runtime"
|
||||
"testing"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/builder"
|
||||
"github.com/docker/docker/image"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/errdefs"
|
||||
|
||||
@@ -44,8 +44,8 @@ func downloadRemote(remoteURL string) (string, io.ReadCloser, error) {
|
||||
// GetWithStatusError does an http.Get() and returns an error if the
|
||||
// status code is 4xx or 5xx.
|
||||
func GetWithStatusError(address string) (resp *http.Response, err error) {
|
||||
// #nosec G107
|
||||
if resp, err = http.Get(address); err != nil {
|
||||
resp, err = http.Get(address) // #nosec G107 -- ignore G107: Potential HTTP request made with variable url
|
||||
if err != nil {
|
||||
if uerr, ok := err.(*url.Error); ok {
|
||||
if derr, ok := uerr.Err.(*net.DNSError); ok && !derr.IsTimeout {
|
||||
return nil, errdefs.NotFound(err)
|
||||
|
||||
@@ -83,55 +83,3 @@ func TestContainerInspect(t *testing.T) {
|
||||
t.Fatalf("expected `name`, got %s", r.Name)
|
||||
}
|
||||
}
|
||||
|
||||
// TestContainerInspectNode tests that the "Node" field is included in the "inspect"
|
||||
// output. This information is only present when connected to a Swarm standalone API.
|
||||
func TestContainerInspectNode(t *testing.T) {
|
||||
client := &Client{
|
||||
client: newMockClient(func(req *http.Request) (*http.Response, error) {
|
||||
content, err := json.Marshal(types.ContainerJSON{
|
||||
ContainerJSONBase: &types.ContainerJSONBase{
|
||||
ID: "container_id",
|
||||
Image: "image",
|
||||
Name: "name",
|
||||
Node: &types.ContainerNode{
|
||||
ID: "container_node_id",
|
||||
Addr: "container_node",
|
||||
Labels: map[string]string{"foo": "bar"},
|
||||
},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &http.Response{
|
||||
StatusCode: http.StatusOK,
|
||||
Body: io.NopCloser(bytes.NewReader(content)),
|
||||
}, nil
|
||||
}),
|
||||
}
|
||||
|
||||
r, err := client.ContainerInspect(context.Background(), "container_id")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if r.ID != "container_id" {
|
||||
t.Fatalf("expected `container_id`, got %s", r.ID)
|
||||
}
|
||||
if r.Image != "image" {
|
||||
t.Fatalf("expected `image`, got %s", r.Image)
|
||||
}
|
||||
if r.Name != "name" {
|
||||
t.Fatalf("expected `name`, got %s", r.Name)
|
||||
}
|
||||
if r.Node.ID != "container_node_id" {
|
||||
t.Fatalf("expected `container_node_id`, got %s", r.Node.ID)
|
||||
}
|
||||
if r.Node.Addr != "container_node" {
|
||||
t.Fatalf("expected `container_node`, got %s", r.Node.Addr)
|
||||
}
|
||||
foo, ok := r.Node.Labels["foo"]
|
||||
if foo != "bar" || !ok {
|
||||
t.Fatalf("expected `bar` for label `foo`")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import (
|
||||
systemrouter "github.com/docker/docker/api/server/router/system"
|
||||
"github.com/docker/docker/api/server/router/volume"
|
||||
buildkit "github.com/docker/docker/builder/builder-next"
|
||||
"github.com/docker/docker/builder/builder-next/exporter"
|
||||
"github.com/docker/docker/builder/dockerfile"
|
||||
"github.com/docker/docker/cmd/dockerd/debug"
|
||||
"github.com/docker/docker/cmd/dockerd/trap"
|
||||
@@ -430,24 +431,27 @@ func newRouterOptions(ctx context.Context, config *config.Config, d *daemon.Daem
|
||||
cgroupParent := newCgroupParent(config)
|
||||
|
||||
bk, err := buildkit.New(ctx, buildkit.Opt{
|
||||
SessionManager: sm,
|
||||
Root: filepath.Join(config.Root, "buildkit"),
|
||||
EngineID: d.ID(),
|
||||
Dist: d.DistributionServices(),
|
||||
ImageTagger: d.ImageService(),
|
||||
NetworkController: d.NetworkController(),
|
||||
DefaultCgroupParent: cgroupParent,
|
||||
RegistryHosts: d.RegistryHosts,
|
||||
BuilderConfig: config.Builder,
|
||||
Rootless: daemon.Rootless(config),
|
||||
IdentityMapping: d.IdentityMapping(),
|
||||
DNSConfig: config.DNSConfig,
|
||||
ApparmorProfile: daemon.DefaultApparmorProfile(),
|
||||
UseSnapshotter: d.UsesSnapshotter(),
|
||||
Snapshotter: d.ImageService().StorageDriver(),
|
||||
ContainerdAddress: config.ContainerdAddr,
|
||||
ContainerdNamespace: config.ContainerdNamespace,
|
||||
ImageExportedCallback: d.ImageExportedByBuildkit,
|
||||
SessionManager: sm,
|
||||
Root: filepath.Join(config.Root, "buildkit"),
|
||||
EngineID: d.ID(),
|
||||
Dist: d.DistributionServices(),
|
||||
ImageTagger: d.ImageService(),
|
||||
NetworkController: d.NetworkController(),
|
||||
DefaultCgroupParent: cgroupParent,
|
||||
RegistryHosts: d.RegistryHosts,
|
||||
BuilderConfig: config.Builder,
|
||||
Rootless: daemon.Rootless(config),
|
||||
IdentityMapping: d.IdentityMapping(),
|
||||
DNSConfig: config.DNSConfig,
|
||||
ApparmorProfile: daemon.DefaultApparmorProfile(),
|
||||
UseSnapshotter: d.UsesSnapshotter(),
|
||||
Snapshotter: d.ImageService().StorageDriver(),
|
||||
ContainerdAddress: config.ContainerdAddr,
|
||||
ContainerdNamespace: config.ContainerdNamespace,
|
||||
Callbacks: exporter.BuildkitCallbacks{
|
||||
Exported: d.ImageExportedByBuildkit,
|
||||
Named: d.ImageNamedByBuildkit,
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
return routerOptions{}, err
|
||||
|
||||
@@ -30,7 +30,6 @@ import (
|
||||
"github.com/docker/docker/layer"
|
||||
libcontainerdtypes "github.com/docker/docker/libcontainerd/types"
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/restartmanager"
|
||||
@@ -345,7 +344,7 @@ func (container *Container) GetResourcePath(path string) (string, error) {
|
||||
}
|
||||
// IMPORTANT - These are paths on the OS where the daemon is running, hence
|
||||
// any filepath operations must be done in an OS-agnostic way.
|
||||
r, e := symlink.FollowSymlinkInScope(filepath.Join(container.BaseFS, containerfs.CleanScopedPath(path)), container.BaseFS)
|
||||
r, e := symlink.FollowSymlinkInScope(filepath.Join(container.BaseFS, cleanScopedPath(path)), container.BaseFS)
|
||||
|
||||
// Log this here on the daemon side as there's otherwise no indication apart
|
||||
// from the error being propagated all the way back to the client. This makes
|
||||
@@ -356,6 +355,18 @@ func (container *Container) GetResourcePath(path string) (string, error) {
|
||||
return r, e
|
||||
}
|
||||
|
||||
// cleanScopedPath prepares the given path to be combined with a mount path or
|
||||
// a drive-letter. On Windows, it removes any existing driveletter (e.g. "C:").
|
||||
// The returned path is always prefixed with a [filepath.Separator].
|
||||
func cleanScopedPath(path string) string {
|
||||
if len(path) >= 2 {
|
||||
if v := filepath.VolumeName(path); len(v) > 0 {
|
||||
path = path[len(v):]
|
||||
}
|
||||
}
|
||||
return filepath.Join(string(filepath.Separator), path)
|
||||
}
|
||||
|
||||
// GetRootResourcePath evaluates `path` in the scope of the container's root, with proper path
|
||||
// sanitisation. Symlinks are all scoped to the root of the container, as
|
||||
// though the container's root was `/`.
|
||||
|
||||
@@ -314,6 +314,7 @@ install_systemd() {
|
||||
[Unit]
|
||||
Description=Docker Application Container Engine (Rootless)
|
||||
Documentation=https://docs.docker.com/go/rootless/
|
||||
Requires=dbus.socket
|
||||
|
||||
[Service]
|
||||
Environment=PATH=$BIN:/sbin:/usr/sbin:$PATH
|
||||
|
||||
@@ -3,6 +3,8 @@ package daemon
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -10,7 +12,15 @@ import (
|
||||
// This is used to log the image creation event for untagged images.
|
||||
// When no tag is given, buildkit doesn't call the image service so it has no
|
||||
// way of knowing the image was created.
|
||||
func (daemon *Daemon) ImageExportedByBuildkit(ctx context.Context, id string, desc ocispec.Descriptor) error {
|
||||
daemon.imageService.LogImageEvent(id, id, "create")
|
||||
return nil
|
||||
func (daemon *Daemon) ImageExportedByBuildkit(ctx context.Context, id string, desc ocispec.Descriptor) {
|
||||
daemon.imageService.LogImageEvent(id, id, events.ActionCreate)
|
||||
}
|
||||
|
||||
// ImageNamedByBuildkit is a callback that is called when an image is tagged by buildkit.
|
||||
// Note: It is only called if the buildkit didn't call the image service itself to perform the tagging.
|
||||
// Currently this only happens when the containerd image store is used.
|
||||
func (daemon *Daemon) ImageNamedByBuildkit(ctx context.Context, ref reference.NamedTagged, desc ocispec.Descriptor) {
|
||||
id := desc.Digest.String()
|
||||
name := reference.FamiliarString(ref)
|
||||
daemon.imageService.LogImageEvent(id, name, events.ActionTag)
|
||||
}
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
|
||||
func TestTmpfsOptionsToGRPC(t *testing.T) {
|
||||
options := [][]string{
|
||||
[]string{"noexec"},
|
||||
[]string{"uid", "12345"},
|
||||
{"noexec"},
|
||||
{"uid", "12345"},
|
||||
}
|
||||
|
||||
expected := `[["noexec"],["uid","12345"]]`
|
||||
@@ -21,8 +21,8 @@ func TestTmpfsOptionsFromGRPC(t *testing.T) {
|
||||
options := `[["noexec"],["uid","12345"]]`
|
||||
|
||||
expected := [][]string{
|
||||
[]string{"noexec"},
|
||||
[]string{"uid", "12345"},
|
||||
{"noexec"},
|
||||
{"uid", "12345"},
|
||||
}
|
||||
actual := tmpfsOptionsFromGRPC(options)
|
||||
|
||||
|
||||
@@ -167,7 +167,7 @@ func TestTmpfsConversion(t *testing.T) {
|
||||
Target: "/bar",
|
||||
Type: mount.TypeTmpfs,
|
||||
TmpfsOptions: &mount.TmpfsOptions{
|
||||
Options: [][]string{[]string{"exec"}},
|
||||
Options: [][]string{{"exec"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -190,7 +190,7 @@ func TestTmpfsConversion(t *testing.T) {
|
||||
Target: "/bar",
|
||||
Type: mount.TypeTmpfs,
|
||||
TmpfsOptions: &mount.TmpfsOptions{
|
||||
Options: [][]string{[]string{"noexec"}},
|
||||
Options: [][]string{{"noexec"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
"time"
|
||||
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/daemon/images"
|
||||
|
||||
@@ -16,10 +16,10 @@ import (
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/rootfs"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/images/archive"
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
"github.com/docker/docker/container"
|
||||
|
||||
@@ -5,8 +5,8 @@ import (
|
||||
"time"
|
||||
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
imagetype "github.com/docker/docker/api/types/image"
|
||||
dimages "github.com/docker/docker/daemon/images"
|
||||
|
||||
@@ -11,9 +11,9 @@ import (
|
||||
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
|
||||
@@ -12,10 +12,10 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/labels"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/filters"
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/metadata"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log/logtest"
|
||||
"github.com/containerd/platforms"
|
||||
imagetypes "github.com/docker/docker/api/types/image"
|
||||
daemonevents "github.com/docker/docker/daemon/events"
|
||||
"github.com/docker/docker/internal/testutils/specialimage"
|
||||
|
||||
@@ -8,8 +8,8 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/moby/buildkit/util/attestation"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -11,10 +11,10 @@ import (
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/pkg/snapshotters"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
|
||||
@@ -12,11 +12,11 @@ import (
|
||||
"github.com/containerd/containerd/images"
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
containerdlabels "github.com/containerd/containerd/labels"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/remotes"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/auxprogress"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
|
||||
@@ -11,7 +11,7 @@ import (
|
||||
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/namespaces"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/internal/testutils/specialimage"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -8,9 +8,9 @@ import (
|
||||
containerdimages "github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/containerd/mount"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/opencontainers/image-spec/identity"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package containerd
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
|
||||
@@ -8,12 +8,12 @@ import (
|
||||
"github.com/containerd/containerd"
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/containerd/plugin"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/containerd/containerd/snapshots"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/container"
|
||||
daemonevents "github.com/docker/docker/daemon/events"
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
|
||||
@@ -17,7 +17,7 @@ import (
|
||||
"github.com/docker/docker/container"
|
||||
"github.com/docker/docker/daemon/config"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
"github.com/docker/docker/internal/containerfs"
|
||||
"github.com/opencontainers/selinux/go-selinux"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
@@ -161,6 +161,8 @@ func (daemon *Daemon) cleanupContainer(container *container.Container, config ba
|
||||
// so that other goroutines don't attempt to concurrently open files
|
||||
// within it. Having any file open on Windows (without the
|
||||
// FILE_SHARE_DELETE flag) will block it from being deleted.
|
||||
//
|
||||
// TODO(thaJeztah): should this be moved to the "container" itself, or possibly be delegated to the graphdriver or snapshotter?
|
||||
container.Lock()
|
||||
err := containerfs.EnsureRemoveAll(container.Root)
|
||||
container.Unlock()
|
||||
|
||||
@@ -37,7 +37,7 @@ import (
|
||||
"github.com/containerd/containerd/pkg/userns"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
"github.com/docker/docker/internal/containerfs"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
units "github.com/docker/go-units"
|
||||
|
||||
@@ -17,10 +17,10 @@ import (
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/daemon/graphdriver/overlayutils"
|
||||
"github.com/docker/docker/internal/containerfs"
|
||||
"github.com/docker/docker/internal/directory"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
"github.com/docker/docker/pkg/directory"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/parsers/kernel"
|
||||
"github.com/moby/locker"
|
||||
|
||||
@@ -14,14 +14,15 @@ import (
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/containerd/containerd/pkg/userns"
|
||||
"github.com/containerd/continuity/fs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/daemon/graphdriver/overlayutils"
|
||||
"github.com/docker/docker/internal/containerfs"
|
||||
"github.com/docker/docker/internal/directory"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/docker/docker/pkg/chrootarchive"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
"github.com/docker/docker/pkg/directory"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
@@ -678,7 +679,6 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
|
||||
return d.naiveDiff.ApplyDiff(id, parent, diff)
|
||||
}
|
||||
|
||||
// never reach here if we are running in UserNS
|
||||
applyDir := d.getDiffPath(id)
|
||||
|
||||
logger.Debugf("Applying tar in %s", applyDir)
|
||||
@@ -686,6 +686,7 @@ func (d *Driver) ApplyDiff(id string, parent string, diff io.Reader) (size int64
|
||||
if err := untar(diff, applyDir, &archive.TarOptions{
|
||||
IDMap: d.idMap,
|
||||
WhiteoutFormat: archive.OverlayWhiteoutFormat,
|
||||
InUserNS: userns.RunningInUserNS(),
|
||||
}); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
|
||||
"github.com/docker/docker/daemon/graphdriver"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/pkg/containerfs"
|
||||
"github.com/docker/docker/internal/containerfs"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/parsers"
|
||||
"github.com/docker/docker/quota"
|
||||
|
||||
@@ -9,9 +9,9 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/leases"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
cerrdefs "github.com/containerd/errdefs"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/errdefs"
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"io"
|
||||
"runtime"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/backend"
|
||||
"github.com/docker/docker/api/types/registry"
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"io"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/events"
|
||||
|
||||
@@ -21,10 +21,10 @@ import (
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/internal/otelutil"
|
||||
"github.com/docker/docker/internal/rootless/mountopts"
|
||||
"github.com/docker/docker/internal/rootless/specconv"
|
||||
"github.com/docker/docker/oci"
|
||||
"github.com/docker/docker/oci/caps"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/rootless/specconv"
|
||||
"github.com/docker/docker/pkg/stringid"
|
||||
volumemounts "github.com/docker/docker/volume/mounts"
|
||||
"github.com/moby/sys/mount"
|
||||
|
||||
@@ -10,8 +10,8 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
|
||||
@@ -6,8 +6,8 @@ import (
|
||||
"context"
|
||||
"sort"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -12,8 +12,8 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/Microsoft/hcsshim/osversion"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/log"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
"github.com/docker/distribution/manifest/schema2"
|
||||
|
||||
@@ -9563,7 +9563,7 @@ paths:
|
||||
|
||||
Containers report these events: `attach`, `commit`, `copy`, `create`, `destroy`, `detach`, `die`, `exec_create`, `exec_detach`, `exec_start`, `exec_die`, `export`, `health_status`, `kill`, `oom`, `pause`, `rename`, `resize`, `restart`, `start`, `stop`, `top`, `unpause`, `update`, and `prune`
|
||||
|
||||
Images report these events: `create, `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, `untag`, and `prune`
|
||||
Images report these events: `create`, `delete`, `import`, `load`, `pull`, `push`, `save`, `tag`, `untag`, and `prune`
|
||||
|
||||
Volumes report these events: `create`, `mount`, `unmount`, `destroy`, and `prune`
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ set -e
|
||||
# the binary version you may also need to update the vendor version to pick up
|
||||
# bug fixes or new APIs, however, usually the Go packages are built from a
|
||||
# commit from the master branch.
|
||||
: "${CONTAINERD_VERSION:=v1.7.18}"
|
||||
: "${CONTAINERD_VERSION:=v1.7.20}"
|
||||
|
||||
install_containerd() (
|
||||
echo "Install containerd version $CONTAINERD_VERSION"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.21.11
|
||||
ARG GO_VERSION=1.21.12
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG PROTOC_VERSION=3.11.4
|
||||
|
||||
|
||||
2
image/cache/compare.go
vendored
2
image/cache/compare.go
vendored
@@ -3,7 +3,7 @@ package cache // import "github.com/docker/docker/image/cache"
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types/container"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -6193,40 +6193,70 @@ func (s *DockerCLIBuildSuite) TestBuildIidFileCleanupOnFail(c *testing.T) {
|
||||
assert.Equal(c, os.IsNotExist(err), true)
|
||||
}
|
||||
|
||||
func (s *DockerCLIBuildSuite) TestBuildEmitsImageCreateEvent(t *testing.T) {
|
||||
for _, tc := range []struct {
|
||||
func (s *DockerCLIBuildSuite) TestBuildEmitsEvents(t *testing.T) {
|
||||
for _, builder := range []struct {
|
||||
buildkit bool
|
||||
}{
|
||||
{buildkit: false},
|
||||
{buildkit: true},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(fmt.Sprintf("buildkit=%v", tc.buildkit), func(t *testing.T) {
|
||||
skip.If(t, DaemonIsWindows, "Buildkit is not supported on Windows")
|
||||
builder := builder
|
||||
for _, tc := range []struct {
|
||||
name string
|
||||
args []string
|
||||
check func(t *testing.T, stdout string)
|
||||
}{
|
||||
{
|
||||
name: "no tag",
|
||||
args: []string{},
|
||||
check: func(t *testing.T, stdout string) {
|
||||
assert.Check(t, is.Contains(stdout, "image create"))
|
||||
assert.Check(t, !strings.Contains(stdout, "image tag"))
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "with tag",
|
||||
args: []string{"-t", "testbuildemitsimagetagevent"},
|
||||
check: func(t *testing.T, stdout string) {
|
||||
assert.Check(t, is.Contains(stdout, "image create"))
|
||||
assert.Check(t, is.Contains(stdout, "image tag"))
|
||||
assert.Check(t, is.Contains(stdout, "testbuildemitsimagetagevent"))
|
||||
},
|
||||
},
|
||||
} {
|
||||
tc := tc
|
||||
t.Run(fmt.Sprintf("buildkit=%v/%s", builder.buildkit, tc.name), func(t *testing.T) {
|
||||
skip.If(t, DaemonIsWindows, "Buildkit is not supported on Windows")
|
||||
|
||||
before := time.Now()
|
||||
time.Sleep(time.Second)
|
||||
before := time.Now()
|
||||
|
||||
b := cli.Docker(cli.Args("build"),
|
||||
build.WithoutCache,
|
||||
build.WithDockerfile("FROM busybox\nRUN echo hi >/hello"),
|
||||
build.WithBuildkit(tc.buildkit),
|
||||
)
|
||||
b.Assert(t, icmd.Success)
|
||||
t.Log(b.Stdout())
|
||||
t.Log(b.Stderr())
|
||||
args := []string{"build"}
|
||||
args = append(args, tc.args...)
|
||||
|
||||
cmd := cli.Docker(
|
||||
cli.Args("events",
|
||||
"--filter", "action=create,type=image",
|
||||
"--since", before.Format(time.RFC3339),
|
||||
),
|
||||
cli.WithTimeout(time.Millisecond*300),
|
||||
cli.WithEnvironmentVariables("DOCKER_API_VERSION=v1.46"), // FIXME(thaJeztah): integration-cli runs docker CLI 17.06; we're "upgrading" the API version to a version it doesn't support here ;)
|
||||
)
|
||||
b := cli.Docker(cli.Args(args...),
|
||||
build.WithoutCache,
|
||||
build.WithDockerfile("FROM busybox\nRUN echo hi >/hello"),
|
||||
build.WithBuildkit(builder.buildkit),
|
||||
)
|
||||
b.Assert(t, icmd.Success)
|
||||
t.Log(b.Stdout())
|
||||
t.Log(b.Stderr())
|
||||
|
||||
t.Log(cmd.Stdout())
|
||||
cmd := cli.Docker(
|
||||
cli.Args("events",
|
||||
"--filter", "type=image",
|
||||
"--since", before.Format(time.RFC3339),
|
||||
),
|
||||
cli.WithTimeout(time.Millisecond*300),
|
||||
cli.WithEnvironmentVariables("DOCKER_API_VERSION=v1.46"), // FIXME(thaJeztah): integration-cli runs docker CLI 17.06; we're "upgrading" the API version to a version it doesn't support here ;)
|
||||
)
|
||||
|
||||
assert.Check(t, is.Contains(cmd.Stdout(), "image create"))
|
||||
})
|
||||
stdout := cmd.Stdout()
|
||||
t.Log(stdout)
|
||||
|
||||
tc.check(t, stdout)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,11 +147,11 @@ func TestImportWithCustomPlatformReject(t *testing.T) {
|
||||
}{
|
||||
{
|
||||
platform: " ",
|
||||
expectedErr: "is an invalid component",
|
||||
expectedErr: "is an invalid OS component",
|
||||
},
|
||||
{
|
||||
platform: "/",
|
||||
expectedErr: "is an invalid component",
|
||||
expectedErr: "is an invalid OS component",
|
||||
},
|
||||
{
|
||||
platform: "macos",
|
||||
|
||||
@@ -14,7 +14,7 @@ import (
|
||||
"github.com/containerd/containerd/content"
|
||||
"github.com/containerd/containerd/content/local"
|
||||
"github.com/containerd/containerd/images"
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/docker/docker/api/types/image"
|
||||
"github.com/docker/docker/errdefs"
|
||||
"github.com/docker/docker/testutil/registry"
|
||||
|
||||
@@ -108,10 +108,10 @@ func TestSaveOCI(t *testing.T) {
|
||||
|
||||
testCases := []testCase{
|
||||
// Busybox by tagged name
|
||||
testCase{image: busybox, expectedContainerdRef: "docker.io/library/busybox:latest", expectedOCIRef: "latest"},
|
||||
{image: busybox, expectedContainerdRef: "docker.io/library/busybox:latest", expectedOCIRef: "latest"},
|
||||
|
||||
// Busybox by ID
|
||||
testCase{image: inspectBusybox.ID},
|
||||
{image: inspectBusybox.ID},
|
||||
}
|
||||
|
||||
if testEnv.DaemonInfo.OSType != "windows" {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"runtime"
|
||||
@@ -788,7 +789,9 @@ func TestNoIP6Tables(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// Test that it's possible to set a sysctl on an interface in the container.
|
||||
// Test that it's possible to set a sysctl on an interface in the container
|
||||
// when using API 1.46 (in later versions of the API, per-interface sysctls
|
||||
// must be set using driver option 'com.docker.network.endpoint.sysctls').
|
||||
// Regression test for https://github.com/moby/moby/issues/47619
|
||||
func TestSetInterfaceSysctl(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows", "no sysctl on Windows")
|
||||
@@ -798,7 +801,7 @@ func TestSetInterfaceSysctl(t *testing.T) {
|
||||
d.StartWithBusybox(ctx, t)
|
||||
defer d.Stop(t)
|
||||
|
||||
c := d.NewClientT(t)
|
||||
c := d.NewClientT(t, client.WithVersion("1.46"))
|
||||
defer c.Close()
|
||||
|
||||
const scName = "net.ipv4.conf.eth0.forwarding"
|
||||
@@ -1055,3 +1058,38 @@ func TestPortMappedHairpin(t *testing.T) {
|
||||
defer c.ContainerRemove(ctx, res.ContainerID, containertypes.RemoveOptions{Force: true})
|
||||
assert.Check(t, is.Contains(res.Stderr.String(), "404 Not Found"))
|
||||
}
|
||||
|
||||
// Check that a container on an IPv4-only network can have a port mapping
|
||||
// from a specific IPv6 host address (using docker-proxy).
|
||||
// Regression test for https://github.com/moby/moby/issues/48067 (which
|
||||
// is about incorrectly reporting this as invalid config).
|
||||
func TestProxy4To6(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows", "uses bridge network and docker-proxy")
|
||||
skip.If(t, testEnv.IsRootless)
|
||||
|
||||
ctx := setupTest(t)
|
||||
d := daemon.New(t)
|
||||
d.StartWithBusybox(ctx, t)
|
||||
defer d.Stop(t)
|
||||
|
||||
c := d.NewClientT(t)
|
||||
defer c.Close()
|
||||
|
||||
const netName = "ipv4net"
|
||||
network.CreateNoError(ctx, t, c, netName)
|
||||
|
||||
serverId := container.Run(ctx, t, c,
|
||||
container.WithNetworkMode(netName),
|
||||
container.WithExposedPorts("80"),
|
||||
container.WithPortMap(nat.PortMap{"80": {{HostIP: "::1"}}}),
|
||||
container.WithCmd("httpd", "-f"),
|
||||
)
|
||||
defer c.ContainerRemove(ctx, serverId, containertypes.RemoveOptions{Force: true})
|
||||
|
||||
inspect := container.Inspect(ctx, t, c, serverId)
|
||||
hostPort := inspect.NetworkSettings.Ports["80/tcp"][0].HostPort
|
||||
|
||||
resp, err := http.Get("http://[::1]:" + hostPort)
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.Equal(resp.StatusCode, 404))
|
||||
}
|
||||
|
||||
@@ -3,11 +3,8 @@
|
||||
package system // import "github.com/docker/docker/integration/system"
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/testutil"
|
||||
req "github.com/docker/docker/testutil/request"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
@@ -28,20 +25,3 @@ func TestInfoBinaryCommits(t *testing.T) {
|
||||
assert.Check(t, "N/A" != info.RuncCommit.ID)
|
||||
assert.Check(t, is.Equal(info.RuncCommit.Expected, info.RuncCommit.ID))
|
||||
}
|
||||
|
||||
func TestInfoAPIVersioned(t *testing.T) {
|
||||
ctx := testutil.StartSpan(baseContext, t)
|
||||
|
||||
res, body, err := req.Get(ctx, "/v1.24/info")
|
||||
assert.NilError(t, err)
|
||||
assert.Check(t, is.DeepEqual(res.StatusCode, http.StatusOK))
|
||||
|
||||
b, err := req.ReadBody(body)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Verify the old response on API 1.24 and older before commit
|
||||
// 6d98e344c7702a8a713cb9e02a19d83a79d3f930.
|
||||
out := string(b)
|
||||
assert.Check(t, is.Contains(out, "ExecutionDriver"))
|
||||
assert.Check(t, is.Contains(out, "not supported"))
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//go:build !darwin && !windows
|
||||
|
||||
package containerfs // import "github.com/docker/docker/pkg/containerfs"
|
||||
package containerfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -11,18 +11,18 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// EnsureRemoveAll wraps `os.RemoveAll` to check for specific errors that can
|
||||
// EnsureRemoveAll wraps [os.RemoveAll] to check for specific errors that can
|
||||
// often be remedied.
|
||||
// Only use `EnsureRemoveAll` if you really want to make every effort to remove
|
||||
// Only use [EnsureRemoveAll] if you really want to make every effort to remove
|
||||
// a directory.
|
||||
//
|
||||
// Because of the way `os.Remove` (and by extension `os.RemoveAll`) works, there
|
||||
// Because of the way [os.Remove] (and by extension [os.RemoveAll]) works, there
|
||||
// can be a race between reading directory entries and then actually attempting
|
||||
// to remove everything in the directory.
|
||||
// These types of errors do not need to be returned since it's ok for the dir to
|
||||
// be gone we can just retry the remove operation.
|
||||
//
|
||||
// This should not return a `os.ErrNotExist` kind of error under any circumstances
|
||||
// This should not return a [os.ErrNotExist] kind of error under any circumstances.
|
||||
func EnsureRemoveAll(dir string) error {
|
||||
notExistErr := make(map[string]bool)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
//go:build !darwin
|
||||
|
||||
package containerfs // import "github.com/docker/docker/pkg/containerfs"
|
||||
package containerfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
@@ -1,6 +1,6 @@
|
||||
//go:build !darwin && !windows
|
||||
|
||||
package containerfs // import "github.com/docker/docker/pkg/containerfs"
|
||||
package containerfs
|
||||
|
||||
import (
|
||||
"os"
|
||||
8
internal/containerfs/rm_windows.go
Normal file
8
internal/containerfs/rm_windows.go
Normal file
@@ -0,0 +1,8 @@
|
||||
package containerfs
|
||||
|
||||
import "os"
|
||||
|
||||
// EnsureRemoveAll is an alias to [os.RemoveAll] on Windows.
|
||||
func EnsureRemoveAll(path string) error {
|
||||
return os.RemoveAll(path)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package directory // import "github.com/docker/docker/pkg/directory"
|
||||
package directory
|
||||
|
||||
import "context"
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package directory // import "github.com/docker/docker/pkg/directory"
|
||||
package directory
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,6 +1,6 @@
|
||||
//go:build linux || freebsd || darwin
|
||||
|
||||
package directory // import "github.com/docker/docker/pkg/directory"
|
||||
package directory
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -22,6 +22,7 @@ func calcSize(ctx context.Context, dir string) (int64, error) {
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
@@ -1,4 +1,4 @@
|
||||
package directory // import "github.com/docker/docker/pkg/directory"
|
||||
package directory
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
// calcSize walks a directory tree and returns its total calcSize in bytes.
|
||||
// calcSize walks a directory tree and returns its total size in bytes.
|
||||
func calcSize(ctx context.Context, dir string) (int64, error) {
|
||||
var size int64
|
||||
err := filepath.Walk(dir, func(d string, fileInfo os.FileInfo, err error) error {
|
||||
@@ -1,4 +1,4 @@
|
||||
package specconv // import "github.com/docker/docker/pkg/rootless/specconv"
|
||||
package specconv
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -1,7 +1,7 @@
|
||||
package specialimage
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/docker/docker/pkg/archive"
|
||||
"github.com/google/uuid"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
package specialimage
|
||||
|
||||
import (
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
|
||||
|
||||
@@ -4,7 +4,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/containerd/containerd/platforms"
|
||||
"github.com/containerd/platforms"
|
||||
"github.com/distribution/reference"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go"
|
||||
|
||||
@@ -60,9 +60,7 @@ func (n *bridgeNetwork) addPortMappings(
|
||||
}
|
||||
|
||||
disableNAT4, disableNAT6 := n.getNATDisabled()
|
||||
if err := validatePortBindings(cfg,
|
||||
!disableNAT4 && len(containerIPv4) > 0,
|
||||
!disableNAT6 && len(containerIPv6) > 0); err != nil {
|
||||
if err := validatePortBindings(cfg, !disableNAT4, !disableNAT6, containerIPv6); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -157,27 +155,32 @@ const validationErrLimit = 6
|
||||
// docker-proxy is used to forward between the default IPv6 address and the
|
||||
// container's IPv4. So, simply disallowing a non-zero IPv6 default when NAT6
|
||||
// is disabled for the network would be incorrect.)
|
||||
func validatePortBindings(pbs []types.PortBinding, nat4, nat6 bool) error {
|
||||
func validatePortBindings(pbs []types.PortBinding, nat4, nat6 bool, cIPv6 net.IP) error {
|
||||
var errs []error
|
||||
for i := range pbs {
|
||||
pb := &pbs[i]
|
||||
disallowHostPort := false
|
||||
if !nat4 && len(pb.HostIP) > 0 && pb.HostIP.To4() != nil && !pb.HostIP.Equal(net.IPv4zero) {
|
||||
// There's no NAT4, so don't allow a nonzero IPv4 host address in the mapping. The port will
|
||||
// accessible via any host interface.
|
||||
// be accessible via any host interface.
|
||||
errs = append(errs,
|
||||
fmt.Errorf("NAT is disabled, omit host address in port mapping %s, or use 0.0.0.0::%d to open port %d for IPv4-only",
|
||||
pb, pb.Port, pb.Port))
|
||||
// The mapping is IPv4-specific but there's no NAT4, so a host port would make no sense.
|
||||
disallowHostPort = true
|
||||
} else if !nat6 && len(pb.HostIP) > 0 && pb.HostIP.To4() == nil && !pb.HostIP.Equal(net.IPv6zero) {
|
||||
// There's no NAT6, so don't allow an IPv6 host address in the mapping. The port will
|
||||
// accessible via any host interface.
|
||||
errs = append(errs,
|
||||
fmt.Errorf("NAT is disabled, omit host address in port mapping %s, or use [::]::%d to open port %d for IPv6-only",
|
||||
pb, pb.Port, pb.Port))
|
||||
// The mapping is IPv6-specific but there's no NAT6, so a host port would make no sense.
|
||||
disallowHostPort = true
|
||||
// If the container has no IPv6 address, the userland proxy will proxy between the
|
||||
// host's IPv6 address and the container's IPv4. So, even with no NAT6, it's ok for
|
||||
// an IPv6 port mapping to include a specific host address or port.
|
||||
if len(cIPv6) > 0 {
|
||||
// There's no NAT6, so don't allow an IPv6 host address in the mapping. The port will
|
||||
// accessible via any host interface.
|
||||
errs = append(errs,
|
||||
fmt.Errorf("NAT is disabled, omit host address in port mapping %s, or use [::]::%d to open port %d for IPv6-only",
|
||||
pb, pb.Port, pb.Port))
|
||||
// The mapping is IPv6-specific but there's no NAT6, so a host port would make no sense.
|
||||
disallowHostPort = true
|
||||
}
|
||||
} else if !nat4 && !nat6 {
|
||||
// There's no NAT, so it would make no sense to specify a host port.
|
||||
disallowHostPort = true
|
||||
|
||||
@@ -186,6 +186,7 @@ func TestValidatePortBindings(t *testing.T) {
|
||||
name string
|
||||
nat4 bool
|
||||
nat6 bool
|
||||
ctrIPv6 net.IP
|
||||
pbs []types.PortBinding
|
||||
expErrs []string
|
||||
}{
|
||||
@@ -196,7 +197,8 @@ func TestValidatePortBindings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no nat with addrs",
|
||||
name: "no nat with addrs",
|
||||
ctrIPv6: newIPNet(t, "fd2c:b48c:69fb::2/128").IP,
|
||||
pbs: []types.PortBinding{
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "233.252.0.2/24").IP, Port: 80},
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "2001:db8::2/64").IP, Port: 80},
|
||||
@@ -246,7 +248,16 @@ func TestValidatePortBindings(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no nat and addrs and ports",
|
||||
name: "nat4 and addrs and ports",
|
||||
nat4: true,
|
||||
pbs: []types.PortBinding{
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "233.252.0.2/24").IP, HostPort: 8080, Port: 80},
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "2001:db8::2/64").IP, HostPort: 8080, Port: 80},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no nat and addrs and ports",
|
||||
ctrIPv6: newIPNet(t, "fd2c:b48c:69fb::2/128").IP,
|
||||
pbs: []types.PortBinding{
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "233.252.0.2/24").IP, HostPort: 8080, Port: 80},
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "2001:db8::2/64").IP, HostPort: 8080, Port: 80},
|
||||
@@ -258,6 +269,17 @@ func TestValidatePortBindings(t *testing.T) {
|
||||
"host port must not be specified in mapping [2001:db8::2]:8080:80/tcp because NAT is disabled",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "no nat no ctrIPv6 and addrs and ports",
|
||||
pbs: []types.PortBinding{
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "233.252.0.2/24").IP, HostPort: 8080, Port: 80},
|
||||
{Proto: types.TCP, HostIP: newIPNet(t, "2001:db8::2/64").IP, HostPort: 8080, Port: 80},
|
||||
},
|
||||
expErrs: []string{
|
||||
"NAT is disabled, omit host address in port mapping 233.252.0.2:8080:80/tcp, or use 0.0.0.0::80 to open port 80 for IPv4-only",
|
||||
"host port must not be specified in mapping 233.252.0.2:8080:80/tcp because NAT is disabled",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "max errs reached",
|
||||
pbs: []types.PortBinding{
|
||||
@@ -283,7 +305,7 @@ func TestValidatePortBindings(t *testing.T) {
|
||||
for _, tc := range testcases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
err := validatePortBindings(tc.pbs, tc.nat4, tc.nat6)
|
||||
err := validatePortBindings(tc.pbs, tc.nat4, tc.nat6, tc.ctrIPv6)
|
||||
if tc.expErrs == nil {
|
||||
assert.Check(t, err)
|
||||
} else {
|
||||
|
||||
@@ -164,8 +164,6 @@ func (aSpace *addrSpace) allocatePredefinedPool(reserved []netip.Prefix) (netip.
|
||||
pdf := aSpace.predefined[pdfID]
|
||||
|
||||
if allocated.Overlaps(pdf.Base) {
|
||||
it.Inc()
|
||||
|
||||
if allocated.Bits() <= pdf.Base.Bits() {
|
||||
// The current 'allocated' prefix is bigger than the 'pdf'
|
||||
// network, thus the block is fully overlapped.
|
||||
@@ -195,6 +193,8 @@ func (aSpace *addrSpace) allocatePredefinedPool(reserved []netip.Prefix) (netip.
|
||||
return makeAlloc(afterPrev), nil
|
||||
}
|
||||
|
||||
it.Inc()
|
||||
|
||||
if netiputil.LastAddr(allocated) == netiputil.LastAddr(pdf.Base) {
|
||||
// The last address of the current 'allocated' prefix is the
|
||||
// same as the last address of the 'pdf' network, it's fully
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package defaultipam
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/netip"
|
||||
"testing"
|
||||
|
||||
@@ -387,3 +388,113 @@ func TestStaticAllocation(t *testing.T) {
|
||||
netip.MustParsePrefix("192.168.3.0/24"),
|
||||
}, cmpopts.EquateComparable(netip.Prefix{})))
|
||||
}
|
||||
|
||||
// Regression test for https://github.com/moby/moby/issues/48069
|
||||
func TestPoolAllocateAndRelease(t *testing.T) {
|
||||
type testClosures struct {
|
||||
alloc func(netname string)
|
||||
release func(netname string)
|
||||
}
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
predefined []*ipamutils.NetworkToSplit
|
||||
reserved []netip.Prefix
|
||||
calls []func(tcs testClosures)
|
||||
tcs testClosures
|
||||
}{
|
||||
{
|
||||
name: "allocate after reserved",
|
||||
predefined: []*ipamutils.NetworkToSplit{
|
||||
{Base: netip.MustParsePrefix("10.0.0.0/24"), Size: 24},
|
||||
{Base: netip.MustParsePrefix("10.0.1.0/24"), Size: 24},
|
||||
{Base: netip.MustParsePrefix("10.1.0.0/16"), Size: 24},
|
||||
},
|
||||
reserved: []netip.Prefix{
|
||||
netip.MustParsePrefix("10.0.0.0/16"),
|
||||
},
|
||||
calls: []func(tcs testClosures){
|
||||
func(tcs testClosures) { tcs.alloc("n1") },
|
||||
func(tcs testClosures) { tcs.alloc("n2") },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reallocate first subnet",
|
||||
predefined: []*ipamutils.NetworkToSplit{
|
||||
{Base: netip.MustParsePrefix("10.0.0.0/8"), Size: 24},
|
||||
},
|
||||
calls: []func(tcs testClosures){
|
||||
func(tcs testClosures) { tcs.alloc("n1") },
|
||||
func(tcs testClosures) { tcs.alloc("n2") },
|
||||
func(tcs testClosures) { tcs.alloc("n3") },
|
||||
func(tcs testClosures) { tcs.release("n1") },
|
||||
func(tcs testClosures) { tcs.alloc("n4") },
|
||||
func(tcs testClosures) { tcs.alloc("n5") },
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "reallocate after release",
|
||||
predefined: []*ipamutils.NetworkToSplit{
|
||||
{Base: netip.MustParsePrefix("10.0.0.0/8"), Size: 24},
|
||||
},
|
||||
calls: []func(tcs testClosures){
|
||||
func(tcs testClosures) { tcs.alloc("n1") },
|
||||
func(tcs testClosures) { tcs.alloc("n2") },
|
||||
func(tcs testClosures) { tcs.alloc("n3") },
|
||||
func(tcs testClosures) { tcs.alloc("n4") },
|
||||
func(tcs testClosures) { tcs.release("n2") },
|
||||
func(tcs testClosures) { tcs.release("n3") },
|
||||
func(tcs testClosures) { tcs.alloc("n5") },
|
||||
func(tcs testClosures) { tcs.alloc("n6") },
|
||||
func(tcs testClosures) { tcs.alloc("n7") },
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
as, err := newAddrSpace(tc.predefined)
|
||||
assert.NilError(t, err)
|
||||
subnetToNetname := map[netip.Prefix]string{}
|
||||
netnameToSubnet := map[string]netip.Prefix{}
|
||||
|
||||
// To avoid passing as,subnetToNetname,netnameToSubnet into each of the
|
||||
// functions in tc.calls (cluttering the list of testcases), create closures
|
||||
// that use them and pass those.
|
||||
tcs := testClosures{
|
||||
// Allocate a pool for netname, check that a subnet is returned that
|
||||
// isn't already allocated, and doesn't overlap with a reserved range.
|
||||
alloc: func(netname string) {
|
||||
subnet, err := as.allocatePredefinedPool(tc.reserved)
|
||||
assert.NilError(t, err)
|
||||
|
||||
otherNetname, exists := subnetToNetname[subnet]
|
||||
assert.Assert(t, !exists, fmt.Sprintf(
|
||||
"subnet %s allocated to %s, reallocated for %s", subnet, otherNetname, netname))
|
||||
for _, reserved := range tc.reserved {
|
||||
assert.Assert(t, !reserved.Overlaps(subnet),
|
||||
fmt.Sprintf("subnet %s allocated in reserved range %s", subnet, reserved))
|
||||
}
|
||||
|
||||
subnetToNetname[subnet] = netname
|
||||
netnameToSubnet[netname] = subnet
|
||||
},
|
||||
// Release a pool for a netname - the test must ensure netname currently
|
||||
// has an allocated subnet.
|
||||
release: func(netname string) {
|
||||
subnet, ok := netnameToSubnet[netname]
|
||||
assert.Assert(t, ok)
|
||||
err := as.releaseSubnet(subnet, netip.Prefix{})
|
||||
assert.NilError(t, err)
|
||||
|
||||
delete(netnameToSubnet, netname)
|
||||
delete(subnetToNetname, subnet)
|
||||
},
|
||||
}
|
||||
|
||||
for _, f := range tc.calls {
|
||||
f(tcs)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/containerd/containerd/pkg/userns"
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/ioutils"
|
||||
@@ -675,9 +674,11 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
|
||||
inUserns, bestEffortXattrs bool
|
||||
chownOpts *idtools.Identity
|
||||
)
|
||||
|
||||
// TODO(thaJeztah): make opts a required argument.
|
||||
if opts != nil {
|
||||
Lchown = !opts.NoLchown
|
||||
inUserns = opts.InUserNS
|
||||
inUserns = opts.InUserNS // TODO(thaJeztah): consider deprecating opts.InUserNS and detect locally.
|
||||
chownOpts = opts.ChownOpts
|
||||
bestEffortXattrs = opts.BestEffortXattrs
|
||||
}
|
||||
@@ -712,6 +713,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
|
||||
|
||||
case tar.TypeBlock, tar.TypeChar:
|
||||
if inUserns { // cannot create devices in a userns
|
||||
log.G(context.TODO()).WithFields(log.Fields{"path": path, "type": hdr.Typeflag}).Debug("skipping device nodes in a userns")
|
||||
return nil
|
||||
}
|
||||
// Handle this is an OS-specific way
|
||||
@@ -722,6 +724,11 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
|
||||
case tar.TypeFifo:
|
||||
// Handle this is an OS-specific way
|
||||
if err := handleTarTypeBlockCharFifo(hdr, path); err != nil {
|
||||
if inUserns && errors.Is(err, syscall.EPERM) {
|
||||
// In most cases, cannot create a fifo if running in user namespace
|
||||
log.G(context.TODO()).WithFields(log.Fields{"error": err, "path": path, "type": hdr.Typeflag}).Debug("creating fifo node in a userns")
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -765,7 +772,7 @@ func createTarFile(path, extractDir string, hdr *tar.Header, reader io.Reader, o
|
||||
}
|
||||
if err := os.Lchown(path, chownOpts.UID, chownOpts.GID); err != nil {
|
||||
msg := "failed to Lchown %q for UID %d, GID %d"
|
||||
if errors.Is(err, syscall.EINVAL) && userns.RunningInUserNS() {
|
||||
if inUserns && errors.Is(err, syscall.EINVAL) {
|
||||
msg += " (try increasing the number of subordinate IDs in /etc/subuid and /etc/subgid)"
|
||||
}
|
||||
return errors.Wrapf(err, msg, path, hdr.Uid, hdr.Gid)
|
||||
@@ -871,11 +878,6 @@ func NewTarballer(srcPath string, options *TarOptions) (*Tarballer, error) {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &Tarballer{
|
||||
// Fix the source path to work with long path names. This is a no-op
|
||||
// on platforms other than Windows.
|
||||
@@ -885,7 +887,7 @@ func NewTarballer(srcPath string, options *TarOptions) (*Tarballer, error) {
|
||||
pipeReader: pipeReader,
|
||||
pipeWriter: pipeWriter,
|
||||
compressWriter: compressWriter,
|
||||
whiteoutConverter: whiteoutConverter,
|
||||
whiteoutConverter: getWhiteoutConverter(options.WhiteoutFormat),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -1080,10 +1082,7 @@ func Unpack(decompressedArchive io.Reader, dest string, options *TarOptions) err
|
||||
defer pools.BufioReader32KPool.Put(trBuf)
|
||||
|
||||
var dirs []*tar.Header
|
||||
whiteoutConverter, err := getWhiteoutConverter(options.WhiteoutFormat, options.InUserNS)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
whiteoutConverter := getWhiteoutConverter(options.WhiteoutFormat)
|
||||
|
||||
// Iterate through the files in the archive.
|
||||
loop:
|
||||
|
||||
@@ -12,14 +12,11 @@ import (
|
||||
"golang.org/x/sys/unix"
|
||||
)
|
||||
|
||||
func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) (tarWhiteoutConverter, error) {
|
||||
func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
|
||||
if format == OverlayWhiteoutFormat {
|
||||
if inUserNS {
|
||||
return nil, errors.New("specifying OverlayWhiteoutFormat is not allowed in userns")
|
||||
}
|
||||
return overlayWhiteoutConverter{}, nil
|
||||
return overlayWhiteoutConverter{}
|
||||
}
|
||||
return nil, nil
|
||||
return nil
|
||||
}
|
||||
|
||||
type overlayWhiteoutConverter struct{}
|
||||
@@ -54,7 +51,7 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os
|
||||
wo = &tar.Header{
|
||||
Typeflag: tar.TypeReg,
|
||||
Mode: hdr.Mode & int64(os.ModePerm),
|
||||
Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir),
|
||||
Name: filepath.Join(hdr.Name, WhiteoutOpaqueDir), // #nosec G305 -- An archive is being created, not extracted.
|
||||
Size: 0,
|
||||
Uid: hdr.Uid,
|
||||
Uname: hdr.Uname,
|
||||
@@ -62,7 +59,7 @@ func (overlayWhiteoutConverter) ConvertWrite(hdr *tar.Header, path string, fi os
|
||||
Gname: hdr.Gname,
|
||||
AccessTime: hdr.AccessTime,
|
||||
ChangeTime: hdr.ChangeTime,
|
||||
} // #nosec G305 -- An archive is being created, not extracted.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,6 @@
|
||||
|
||||
package archive // import "github.com/docker/docker/pkg/archive"
|
||||
|
||||
func getWhiteoutConverter(format WhiteoutFormat, inUserNS bool) (tarWhiteoutConverter, error) {
|
||||
return nil, nil
|
||||
func getWhiteoutConverter(format WhiteoutFormat) tarWhiteoutConverter {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"strings"
|
||||
"syscall"
|
||||
|
||||
"github.com/containerd/containerd/pkg/userns"
|
||||
"github.com/docker/docker/pkg/idtools"
|
||||
"github.com/docker/docker/pkg/system"
|
||||
"golang.org/x/sys/unix"
|
||||
@@ -95,7 +94,10 @@ func getFileUIDGID(stat interface{}) (idtools.Identity, error) {
|
||||
}
|
||||
|
||||
// handleTarTypeBlockCharFifo is an OS-specific helper function used by
|
||||
// createTarFile to handle the following types of header: Block; Char; Fifo
|
||||
// createTarFile to handle the following types of header: Block; Char; Fifo.
|
||||
//
|
||||
// Creating device nodes is not supported when running in a user namespace,
|
||||
// produces a [syscall.EPERM] in most cases.
|
||||
func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
|
||||
mode := uint32(hdr.Mode & 0o7777)
|
||||
switch hdr.Typeflag {
|
||||
@@ -107,12 +109,7 @@ func handleTarTypeBlockCharFifo(hdr *tar.Header, path string) error {
|
||||
mode |= unix.S_IFIFO
|
||||
}
|
||||
|
||||
err := system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor)))
|
||||
if errors.Is(err, syscall.EPERM) && userns.RunningInUserNS() {
|
||||
// In most cases, cannot create a device if running in user namespace
|
||||
err = nil
|
||||
}
|
||||
return err
|
||||
return system.Mknod(path, mode, int(system.Mkdev(hdr.Devmajor, hdr.Devminor)))
|
||||
}
|
||||
|
||||
func handleLChmod(hdr *tar.Header, path string, hdrInfo os.FileInfo) error {
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
package containerfs // import "github.com/docker/docker/pkg/containerfs"
|
||||
|
||||
import "path/filepath"
|
||||
|
||||
// CleanScopedPath prepares the given path to be combined with a mount path or
|
||||
// a drive-letter. On Windows, it removes any existing driveletter (e.g. "C:").
|
||||
// The returned path is always prefixed with a [filepath.Separator].
|
||||
func CleanScopedPath(path string) string {
|
||||
if len(path) >= 2 {
|
||||
if v := filepath.VolumeName(path); len(v) > 0 {
|
||||
path = path[len(v):]
|
||||
}
|
||||
}
|
||||
return filepath.Join(string(filepath.Separator), path)
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user