mirror of
https://github.com/moby/moby.git
synced 2026-01-12 03:01:38 +00:00
Compare commits
16 Commits
docker-29.
...
v26.1.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8e96db1c32 | ||
|
|
c21fe3efa3 | ||
|
|
86af4eddb3 | ||
|
|
73511cdee0 | ||
|
|
9326cda7bf | ||
|
|
76fcf9a8e0 | ||
|
|
ef1912d8b6 | ||
|
|
10739af81a | ||
|
|
ac2de55998 | ||
|
|
9a2b531127 | ||
|
|
2f5bbbe16b | ||
|
|
40618081f1 | ||
|
|
21da192ae4 | ||
|
|
2c91196921 | ||
|
|
a9a8787c93 | ||
|
|
c9689eccf5 |
2
.github/workflows/.windows.yml
vendored
2
.github/workflows/.windows.yml
vendored
@@ -19,7 +19,7 @@ on:
|
||||
default: false
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.9"
|
||||
GO_VERSION: "1.21.10"
|
||||
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.9"
|
||||
GO_VERSION: "1.21.10"
|
||||
DESTDIR: ./build
|
||||
|
||||
jobs:
|
||||
|
||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -13,7 +13,7 @@ on:
|
||||
pull_request:
|
||||
|
||||
env:
|
||||
GO_VERSION: "1.21.9"
|
||||
GO_VERSION: "1.21.10"
|
||||
GIT_PAGER: "cat"
|
||||
PAGER: "cat"
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1.7
|
||||
|
||||
ARG GO_VERSION=1.21.9
|
||||
ARG GO_VERSION=1.21.10
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
ARG XX_VERSION=1.4.0
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
# This represents the bare minimum required to build and test Docker.
|
||||
|
||||
ARG GO_VERSION=1.21.9
|
||||
ARG GO_VERSION=1.21.10
|
||||
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG GOLANG_IMAGE="golang:${GO_VERSION}-${BASE_DEBIAN_DISTRO}"
|
||||
|
||||
@@ -161,7 +161,7 @@ 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.9
|
||||
ARG GO_VERSION=1.21.10
|
||||
ARG GOTESTSUM_VERSION=v1.8.2
|
||||
ARG GOWINRES_VERSION=v0.3.1
|
||||
ARG CONTAINERD_VERSION=v1.7.15
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# syntax=docker/dockerfile:1
|
||||
|
||||
ARG GO_VERSION=1.21.9
|
||||
ARG GO_VERSION=1.21.10
|
||||
ARG BASE_DEBIAN_DISTRO="bookworm"
|
||||
ARG PROTOC_VERSION=3.11.4
|
||||
|
||||
|
||||
@@ -47,6 +47,13 @@ func WithNetworkMode(mode string) func(*TestContainerConfig) {
|
||||
}
|
||||
}
|
||||
|
||||
// WithDNS sets external DNS servers for the container
|
||||
func WithDNS(dns []string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
c.HostConfig.DNS = append([]string(nil), dns...)
|
||||
}
|
||||
}
|
||||
|
||||
// WithSysctls sets sysctl options for the container
|
||||
func WithSysctls(sysctls map[string]string) func(*TestContainerConfig) {
|
||||
return func(c *TestContainerConfig) {
|
||||
|
||||
@@ -9,6 +9,8 @@ import (
|
||||
"github.com/docker/docker/integration/internal/network"
|
||||
"github.com/docker/docker/testutil"
|
||||
"github.com/docker/docker/testutil/daemon"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
"gotest.tools/v3/poll"
|
||||
"gotest.tools/v3/skip"
|
||||
)
|
||||
@@ -33,3 +35,59 @@ func TestDaemonDNSFallback(t *testing.T) {
|
||||
|
||||
poll.WaitOn(t, container.IsSuccessful(ctx, c, cid), poll.WithDelay(100*time.Millisecond), poll.WithTimeout(10*time.Second))
|
||||
}
|
||||
|
||||
// Check that, when the internal DNS server's address is supplied as an external
|
||||
// DNS server, the daemon doesn't start talking to itself.
|
||||
func TestIntDNSAsExtDNS(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows", "cannot start daemon on Windows test run")
|
||||
skip.If(t, testEnv.IsRemoteDaemon, "cannot start daemon on remote test run")
|
||||
|
||||
ctx := setupTest(t)
|
||||
|
||||
d := daemon.New(t)
|
||||
d.StartWithBusybox(ctx, t)
|
||||
defer d.Stop(t)
|
||||
|
||||
c := d.NewClientT(t)
|
||||
defer c.Close()
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
extServers []string
|
||||
expExitCode int
|
||||
expStdout string
|
||||
}{
|
||||
{
|
||||
name: "only self",
|
||||
extServers: []string{"127.0.0.11"},
|
||||
expExitCode: 1,
|
||||
expStdout: "SERVFAIL",
|
||||
},
|
||||
{
|
||||
name: "self then ext",
|
||||
extServers: []string{"127.0.0.11", "8.8.8.8"},
|
||||
expExitCode: 0,
|
||||
expStdout: "Non-authoritative answer",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := testutil.StartSpan(ctx, t)
|
||||
|
||||
const netName = "testnet"
|
||||
network.CreateNoError(ctx, t, c, netName)
|
||||
defer network.RemoveNoError(ctx, t, c, netName)
|
||||
|
||||
res := container.RunAttach(ctx, t, c,
|
||||
container.WithNetworkMode(netName),
|
||||
container.WithDNS(tc.extServers),
|
||||
container.WithCmd("nslookup", "docker.com"),
|
||||
)
|
||||
defer c.ContainerRemove(ctx, res.ContainerID, containertypes.RemoveOptions{Force: true})
|
||||
|
||||
assert.Check(t, is.Equal(res.ExitCode, tc.expExitCode))
|
||||
assert.Check(t, is.Contains(res.Stdout.String(), tc.expStdout))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +469,6 @@ func TestDefaultBridgeAddresses(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
|
||||
|
||||
ctx := setupTest(t)
|
||||
d := daemon.New(t)
|
||||
|
||||
type testStep struct {
|
||||
stepName string
|
||||
@@ -487,13 +486,13 @@ func TestDefaultBridgeAddresses(t *testing.T) {
|
||||
{
|
||||
stepName: "Set up initial UL prefix",
|
||||
fixedCIDRV6: "fd1c:f1a0:5d8d:aaaa::/64",
|
||||
expAddrs: []string{"fd1c:f1a0:5d8d:aaaa::1/64", "fe80::1/64"},
|
||||
expAddrs: []string{"fd1c:f1a0:5d8d:aaaa::1/64", "fe80::"},
|
||||
},
|
||||
{
|
||||
// Modify that prefix, the default bridge's address must be deleted and re-added.
|
||||
stepName: "Modify UL prefix - address change",
|
||||
fixedCIDRV6: "fd1c:f1a0:5d8d:bbbb::/64",
|
||||
expAddrs: []string{"fd1c:f1a0:5d8d:bbbb::1/64", "fe80::1/64"},
|
||||
expAddrs: []string{"fd1c:f1a0:5d8d:bbbb::1/64", "fe80::"},
|
||||
},
|
||||
{
|
||||
// Modify the prefix length, the default bridge's address should not change.
|
||||
@@ -501,7 +500,7 @@ func TestDefaultBridgeAddresses(t *testing.T) {
|
||||
fixedCIDRV6: "fd1c:f1a0:5d8d:bbbb::/80",
|
||||
// The prefix length displayed by 'ip a' is not updated - it's informational, and
|
||||
// can't be changed without unnecessarily deleting and re-adding the address.
|
||||
expAddrs: []string{"fd1c:f1a0:5d8d:bbbb::1/64", "fe80::1/64"},
|
||||
expAddrs: []string{"fd1c:f1a0:5d8d:bbbb::1/64", "fe80::"},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -511,14 +510,14 @@ func TestDefaultBridgeAddresses(t *testing.T) {
|
||||
{
|
||||
stepName: "Standard LL subnet prefix",
|
||||
fixedCIDRV6: "fe80::/64",
|
||||
expAddrs: []string{"fe80::1/64"},
|
||||
expAddrs: []string{"fe80::"},
|
||||
},
|
||||
{
|
||||
// Modify that prefix, the default bridge's address must be deleted and re-added.
|
||||
// The bridge must still have an address in the required (standard) LL subnet.
|
||||
stepName: "Nonstandard LL prefix - address change",
|
||||
fixedCIDRV6: "fe80:1234::/32",
|
||||
expAddrs: []string{"fe80:1234::1/32", "fe80::1/64"},
|
||||
expAddrs: []string{"fe80:1234::1/32", "fe80::"},
|
||||
},
|
||||
{
|
||||
// Modify the prefix length, the addresses should not change.
|
||||
@@ -526,32 +525,48 @@ func TestDefaultBridgeAddresses(t *testing.T) {
|
||||
fixedCIDRV6: "fe80:1234::/64",
|
||||
// The prefix length displayed by 'ip a' is not updated - it's informational, and
|
||||
// can't be changed without unnecessarily deleting and re-adding the address.
|
||||
expAddrs: []string{"fe80:1234::1/", "fe80::1/64"},
|
||||
expAddrs: []string{"fe80:1234::1/", "fe80::"},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
for _, step := range tc.steps {
|
||||
// Check that the daemon starts - regression test for:
|
||||
// https://github.com/moby/moby/issues/46829
|
||||
d.Start(t, "--experimental", "--ipv6", "--ip6tables", "--fixed-cidr-v6="+step.fixedCIDRV6)
|
||||
d.Stop(t)
|
||||
for _, preserveKernelLL := range []bool{false, true} {
|
||||
var dopts []daemon.Option
|
||||
if preserveKernelLL {
|
||||
dopts = append(dopts, daemon.WithEnvVars("DOCKER_BRIDGE_PRESERVE_KERNEL_LL=1"))
|
||||
}
|
||||
d := daemon.New(t, dopts...)
|
||||
c := d.NewClientT(t)
|
||||
|
||||
// Check that the expected addresses have been applied to the bridge. (Skip in
|
||||
// rootless mode, because the bridge is in a different network namespace.)
|
||||
if !testEnv.IsRootless() {
|
||||
res := testutil.RunCommand(ctx, "ip", "-6", "addr", "show", "docker0")
|
||||
assert.Equal(t, res.ExitCode, 0, step.stepName)
|
||||
stdout := res.Stdout()
|
||||
for _, expAddr := range step.expAddrs {
|
||||
assert.Check(t, is.Contains(stdout, expAddr))
|
||||
for _, tc := range testcases {
|
||||
for _, step := range tc.steps {
|
||||
tcName := fmt.Sprintf("kernel_ll_%v/%s/%s", preserveKernelLL, tc.name, step.stepName)
|
||||
t.Run(tcName, func(t *testing.T) {
|
||||
ctx := testutil.StartSpan(ctx, t)
|
||||
// Check that the daemon starts - regression test for:
|
||||
// https://github.com/moby/moby/issues/46829
|
||||
d.StartWithBusybox(ctx, t, "--experimental", "--ipv6", "--ip6tables", "--fixed-cidr-v6="+step.fixedCIDRV6)
|
||||
|
||||
// Start a container, so that the bridge is set "up" and gets a kernel_ll address.
|
||||
cID := container.Run(ctx, t, c)
|
||||
defer c.ContainerRemove(ctx, cID, containertypes.RemoveOptions{Force: true})
|
||||
|
||||
d.Stop(t)
|
||||
|
||||
// Check that the expected addresses have been applied to the bridge. (Skip in
|
||||
// rootless mode, because the bridge is in a different network namespace.)
|
||||
if !testEnv.IsRootless() {
|
||||
res := testutil.RunCommand(ctx, "ip", "-6", "addr", "show", "docker0")
|
||||
assert.Equal(t, res.ExitCode, 0, step.stepName)
|
||||
stdout := res.Stdout()
|
||||
for _, expAddr := range step.expAddrs {
|
||||
assert.Check(t, is.Contains(stdout, expAddr))
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -738,3 +753,78 @@ func TestSetInterfaceSysctl(t *testing.T) {
|
||||
stdout := runRes.Stdout.String()
|
||||
assert.Check(t, is.Contains(stdout, scName))
|
||||
}
|
||||
|
||||
// With a read-only "/proc/sys/net" filesystem (simulated using env var
|
||||
// DOCKER_TEST_RO_DISABLE_IPV6), check that if IPv6 can't be disabled on a
|
||||
// container interface, container creation fails - unless the error is ignored by
|
||||
// setting env var DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE=1.
|
||||
// Regression test for https://github.com/moby/moby/issues/47751
|
||||
func TestReadOnlySlashProc(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows")
|
||||
|
||||
ctx := setupTest(t)
|
||||
|
||||
testcases := []struct {
|
||||
name string
|
||||
daemonEnv []string
|
||||
expErr string
|
||||
}{
|
||||
{
|
||||
name: "Normality",
|
||||
},
|
||||
{
|
||||
name: "Read only no workaround",
|
||||
daemonEnv: []string{
|
||||
"DOCKER_TEST_RO_DISABLE_IPV6=1",
|
||||
},
|
||||
expErr: "failed to disable IPv6 on container's interface eth0, set env var DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE=1 to ignore this error",
|
||||
},
|
||||
{
|
||||
name: "Read only with workaround",
|
||||
daemonEnv: []string{
|
||||
"DOCKER_TEST_RO_DISABLE_IPV6=1",
|
||||
"DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE=1",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testcases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
ctx := testutil.StartSpan(ctx, t)
|
||||
|
||||
d := daemon.New(t, daemon.WithEnvVars(tc.daemonEnv...))
|
||||
d.StartWithBusybox(ctx, t)
|
||||
defer d.Stop(t)
|
||||
c := d.NewClientT(t)
|
||||
|
||||
const net4Name = "testnet4"
|
||||
network.CreateNoError(ctx, t, c, net4Name)
|
||||
defer network.RemoveNoError(ctx, t, c, net4Name)
|
||||
id4 := container.Create(ctx, t, c,
|
||||
container.WithNetworkMode(net4Name),
|
||||
container.WithCmd("ls"),
|
||||
)
|
||||
defer c.ContainerRemove(ctx, id4, containertypes.RemoveOptions{Force: true})
|
||||
err := c.ContainerStart(ctx, id4, containertypes.StartOptions{})
|
||||
if tc.expErr == "" {
|
||||
assert.Check(t, err)
|
||||
} else {
|
||||
assert.Check(t, is.ErrorContains(err, tc.expErr))
|
||||
}
|
||||
|
||||
// It should always be possible to create a container on an IPv6 network (IPv6
|
||||
// doesn't need to be disabled on the interface).
|
||||
const net6Name = "testnet6"
|
||||
network.CreateNoError(ctx, t, c, net6Name,
|
||||
network.WithIPv6(),
|
||||
network.WithIPAM("fd5c:15e3:0b62:5395::/64", "fd5c:15e3:0b62:5395::1"),
|
||||
)
|
||||
defer network.RemoveNoError(ctx, t, c, net6Name)
|
||||
id6 := container.Run(ctx, t, c,
|
||||
container.WithNetworkMode(net6Name),
|
||||
container.WithCmd("ls"),
|
||||
)
|
||||
defer c.ContainerRemove(ctx, id6, containertypes.RemoveOptions{Force: true})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,14 @@ package networking
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
containertypes "github.com/docker/docker/api/types/container"
|
||||
"github.com/docker/docker/api/types/mount"
|
||||
"github.com/docker/docker/integration/internal/container"
|
||||
"github.com/docker/docker/integration/internal/network"
|
||||
"github.com/docker/docker/testutil/daemon"
|
||||
@@ -134,6 +137,59 @@ func TestInternalNetworkDNS(t *testing.T) {
|
||||
assert.Check(t, is.Contains(res.Stdout(), network.DNSRespAddr))
|
||||
}
|
||||
|
||||
// Check that '--dns' can be used to name a server inside a '--internal' network.
|
||||
// Regression test for https://github.com/moby/moby/issues/47822
|
||||
func TestInternalNetworkLocalDNS(t *testing.T) {
|
||||
skip.If(t, testEnv.DaemonInfo.OSType == "windows", "No internal networks on Windows")
|
||||
skip.If(t, testEnv.IsRootless, "Can't write an accessible dnsd.conf in rootless mode")
|
||||
ctx := setupTest(t)
|
||||
|
||||
d := daemon.New(t)
|
||||
d.StartWithBusybox(ctx, t)
|
||||
defer d.Stop(t)
|
||||
|
||||
c := d.NewClientT(t)
|
||||
defer c.Close()
|
||||
|
||||
intNetName := "intnet"
|
||||
network.CreateNoError(ctx, t, c, intNetName,
|
||||
network.WithDriver("bridge"),
|
||||
network.WithInternal(),
|
||||
)
|
||||
defer network.RemoveNoError(ctx, t, c, intNetName)
|
||||
|
||||
// Write a config file for busybox's dnsd.
|
||||
td := t.TempDir()
|
||||
fname := path.Join(td, "dnsd.conf")
|
||||
err := os.WriteFile(fname, []byte("foo.example 192.0.2.42\n"), 0644)
|
||||
assert.NilError(t, err)
|
||||
|
||||
// Start a DNS server on the internal network.
|
||||
serverId := container.Run(ctx, t, c,
|
||||
container.WithNetworkMode(intNetName),
|
||||
container.WithMount(mount.Mount{
|
||||
Type: mount.TypeBind,
|
||||
Source: fname,
|
||||
Target: "/etc/dnsd.conf",
|
||||
}),
|
||||
container.WithCmd("dnsd"),
|
||||
)
|
||||
defer c.ContainerRemove(ctx, serverId, containertypes.RemoveOptions{Force: true})
|
||||
|
||||
// Get the DNS server's address.
|
||||
inspect := container.Inspect(ctx, t, c, serverId)
|
||||
serverIP := inspect.NetworkSettings.Networks[intNetName].IPAddress
|
||||
|
||||
// Query the internal network's DNS server (via the daemon's internal DNS server).
|
||||
res := container.RunAttach(ctx, t, c,
|
||||
container.WithNetworkMode(intNetName),
|
||||
container.WithDNS([]string{serverIP}),
|
||||
container.WithCmd("nslookup", "-type=A", "foo.example"),
|
||||
)
|
||||
defer c.ContainerRemove(ctx, res.ContainerID, containertypes.RemoveOptions{Force: true})
|
||||
assert.Check(t, is.Contains(res.Stdout.String(), "192.0.2.42"))
|
||||
}
|
||||
|
||||
// TestNslookupWindows checks that nslookup gets results from external DNS.
|
||||
// Regression test for https://github.com/moby/moby/issues/46792
|
||||
func TestNslookupWindows(t *testing.T) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/log"
|
||||
"github.com/docker/docker/errdefs"
|
||||
@@ -73,18 +74,20 @@ func (i *bridgeInterface) addresses(family int) ([]netlink.Addr, error) {
|
||||
func getRequiredIPv6Addrs(config *networkConfiguration) (requiredAddrs map[netip.Addr]netip.Prefix, err error) {
|
||||
requiredAddrs = make(map[netip.Addr]netip.Prefix)
|
||||
|
||||
// Always give the bridge 'fe80::1' - every interface is required to have an
|
||||
// address in 'fe80::/64'. Linux may assign an address, but we'll replace it with
|
||||
// 'fe80::1'. Then, if the configured prefix is 'fe80::/64', the IPAM pool
|
||||
// assigned address will not be a second address in the LL subnet.
|
||||
ra, ok := netiputil.ToPrefix(bridgeIPv6)
|
||||
if !ok {
|
||||
err = fmt.Errorf("Failed to convert Link-Local IPv6 address to netip.Prefix")
|
||||
return nil, err
|
||||
if os.Getenv("DOCKER_BRIDGE_PRESERVE_KERNEL_LL") != "1" {
|
||||
// Always give the bridge 'fe80::1' - every interface is required to have an
|
||||
// address in 'fe80::/64'. Linux may assign an address, but we'll replace it with
|
||||
// 'fe80::1'. Then, if the configured prefix is 'fe80::/64', the IPAM pool
|
||||
// assigned address will not be a second address in the LL subnet.
|
||||
ra, ok := netiputil.ToPrefix(bridgeIPv6)
|
||||
if !ok {
|
||||
err = fmt.Errorf("Failed to convert Link-Local IPv6 address to netip.Prefix")
|
||||
return nil, err
|
||||
}
|
||||
requiredAddrs[ra.Addr()] = ra
|
||||
}
|
||||
requiredAddrs[ra.Addr()] = ra
|
||||
|
||||
ra, ok = netiputil.ToPrefix(config.AddressIPv6)
|
||||
ra, ok := netiputil.ToPrefix(config.AddressIPv6)
|
||||
if !ok {
|
||||
err = fmt.Errorf("failed to convert bridge IPv6 address '%s' to netip.Prefix", config.AddressIPv6.String())
|
||||
return nil, err
|
||||
@@ -116,6 +119,14 @@ func (i *bridgeInterface) programIPv6Addresses(config *networkConfiguration) err
|
||||
if !ok {
|
||||
return errdefs.System(fmt.Errorf("Failed to convert IPv6 address '%s' to netip.Addr", config.AddressIPv6))
|
||||
}
|
||||
// Optionally, avoid deleting the kernel-assigned link local address.
|
||||
// (Don't delete fe80::1 either - if it was previously assigned to the bridge, and the
|
||||
// kernel_ll address was deleted, the bridge won't get a new kernel_ll address.)
|
||||
if os.Getenv("DOCKER_BRIDGE_PRESERVE_KERNEL_LL") == "1" {
|
||||
if p, _ := ea.Prefix(64); p == linkLocalPrefix {
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Ignore the prefix length when comparing addresses, it's informational
|
||||
// (RFC-5942 section 4), and removing/re-adding an address that's still valid
|
||||
// would disrupt traffic on live-restore.
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
|
||||
"github.com/containerd/log"
|
||||
@@ -13,6 +14,9 @@ import (
|
||||
// bridgeIPv6 is the default, link-local IPv6 address for the bridge (fe80::1/64)
|
||||
var bridgeIPv6 = &net.IPNet{IP: net.ParseIP("fe80::1"), Mask: net.CIDRMask(64, 128)}
|
||||
|
||||
// Standard link local prefix
|
||||
var linkLocalPrefix = netip.MustParsePrefix("fe80::/64")
|
||||
|
||||
const (
|
||||
ipv6ForwardConfPerm = 0o644
|
||||
ipv6ForwardConfDefault = "/proc/sys/net/ipv6/conf/default/forwarding"
|
||||
|
||||
@@ -646,17 +646,47 @@ func setIPv6(nspath, iface string, enable bool) error {
|
||||
value = '0'
|
||||
}
|
||||
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
if curVal, err := os.ReadFile(path); err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
log.G(context.TODO()).WithError(err).Warn("Cannot configure IPv6 forwarding on container interface. Has IPv6 been disabled in this node's kernel?")
|
||||
if enable {
|
||||
log.G(context.TODO()).WithError(err).Warn("Cannot enable IPv6 on container interface. Has IPv6 been disabled in this node's kernel?")
|
||||
} else {
|
||||
log.G(context.TODO()).WithError(err).Debug("Not disabling IPv6 on container interface. Has IPv6 been disabled in this node's kernel?")
|
||||
}
|
||||
return
|
||||
}
|
||||
errCh <- err
|
||||
return
|
||||
} else if len(curVal) > 0 && curVal[0] == value {
|
||||
// Nothing to do, the setting is already correct.
|
||||
return
|
||||
}
|
||||
|
||||
if err = os.WriteFile(path, []byte{value, '\n'}, 0o644); err != nil {
|
||||
errCh <- fmt.Errorf("failed to %s IPv6 forwarding for container's interface %s: %w", action, iface, err)
|
||||
if err = os.WriteFile(path, []byte{value, '\n'}, 0o644); err != nil || os.Getenv("DOCKER_TEST_RO_DISABLE_IPV6") != "" {
|
||||
logger := log.G(context.TODO()).WithFields(log.Fields{
|
||||
"error": err,
|
||||
"interface": iface,
|
||||
})
|
||||
if enable {
|
||||
// The user asked for IPv6 on the interface, and we can't give it to them.
|
||||
// But, in line with the IsNotExist case above, just log.
|
||||
logger.Warn("Cannot enable IPv6 on container interface, continuing.")
|
||||
} else if os.Getenv("DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE") == "1" {
|
||||
// TODO(robmry) - remove this escape hatch for https://github.com/moby/moby/issues/47751
|
||||
// If the "/proc" file exists but isn't writable, we can't disable IPv6, which is
|
||||
// https://github.com/moby/moby/security/advisories/GHSA-x84c-p2g9-rqv9 ... so,
|
||||
// the user is required to override the error (or configure IPv6, or disable IPv6
|
||||
// by default in the OS, or make the "/proc" file writable). Once it's possible
|
||||
// to enable IPv6 without having to configure IPAM etc, the env var should be
|
||||
// removed. Then the user will have to explicitly enable IPv6 if it can't be
|
||||
// disabled on the interface.
|
||||
logger.Info("Cannot disable IPv6 on container interface but DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE=1, continuing.")
|
||||
} else {
|
||||
logger.Error("Cannot disable IPv6 on container interface. Set env var DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE=1 to ignore.")
|
||||
errCh <- fmt.Errorf(
|
||||
"failed to %s IPv6 on container's interface %s, set env var DOCKER_ALLOW_IPV6_ON_IPV4_INTERFACE=1 to ignore this error",
|
||||
action, iface)
|
||||
}
|
||||
return
|
||||
}
|
||||
}()
|
||||
|
||||
@@ -224,13 +224,7 @@ func (r *Resolver) Stop() {
|
||||
// when forwarding queries, unless SetExtServersForSrc has configured servers
|
||||
// for the DNS client making the request.
|
||||
func (r *Resolver) SetExtServers(extDNS []extDNSEntry) {
|
||||
l := len(extDNS)
|
||||
if l > maxExtDNS {
|
||||
l = maxExtDNS
|
||||
}
|
||||
for i := 0; i < l; i++ {
|
||||
r.extDNSList[i] = extDNS[i]
|
||||
}
|
||||
copy(r.extDNSList[:], r.filterExtServers(extDNS))
|
||||
}
|
||||
|
||||
// SetForwardingPolicy re-configures the embedded DNS resolver to either enable or disable forwarding DNS queries to
|
||||
@@ -244,7 +238,7 @@ func (r *Resolver) SetForwardingPolicy(policy bool) {
|
||||
// in preference to servers set by SetExtServers. Supplying a nil or empty extDNS
|
||||
// deletes nameservers for srcAddr.
|
||||
func (r *Resolver) SetExtServersForSrc(srcAddr netip.Addr, extDNS []extDNSEntry) error {
|
||||
r.ipToExtDNS.set(srcAddr, extDNS)
|
||||
r.ipToExtDNS.set(srcAddr, r.filterExtServers(extDNS))
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -258,6 +252,23 @@ func (r *Resolver) ResolverOptions() []string {
|
||||
return []string{"ndots:0"}
|
||||
}
|
||||
|
||||
// filterExtServers removes the resolver's own address from extDNS if present,
|
||||
// and returns the result.
|
||||
func (r *Resolver) filterExtServers(extDNS []extDNSEntry) []extDNSEntry {
|
||||
result := make([]extDNSEntry, 0, len(extDNS))
|
||||
for _, e := range extDNS {
|
||||
if !e.HostLoopback {
|
||||
if ra, _ := netip.ParseAddr(e.IPStr); ra == r.listenAddress {
|
||||
log.G(context.TODO()).Infof("[resolver] not using own address (%s) as an external DNS server",
|
||||
r.listenAddress)
|
||||
continue
|
||||
}
|
||||
}
|
||||
result = append(result, e)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
//nolint:gosec // The RNG is not used in a security-sensitive context.
|
||||
var (
|
||||
shuffleRNG = rand.New(rand.NewSource(time.Now().Unix()))
|
||||
@@ -475,17 +486,15 @@ func (r *Resolver) serveDNS(w dns.ResponseWriter, query *dns.Msg) {
|
||||
return
|
||||
}
|
||||
|
||||
if r.proxyDNS.Load() {
|
||||
// If the user sets ndots > 0 explicitly and the query is
|
||||
// in the root domain don't forward it out. We will return
|
||||
// failure and let the client retry with the search domain
|
||||
// attached.
|
||||
if (queryType == dns.TypeA || queryType == dns.TypeAAAA) && r.backend.NdotsSet() &&
|
||||
!strings.Contains(strings.TrimSuffix(queryName, "."), ".") {
|
||||
resp = createRespMsg(query)
|
||||
} else {
|
||||
resp = r.forwardExtDNS(ctx, w.LocalAddr().Network(), w.RemoteAddr(), query)
|
||||
}
|
||||
// If the user sets ndots > 0 explicitly and the query is
|
||||
// in the root domain don't forward it out. We will return
|
||||
// failure and let the client retry with the search domain
|
||||
// attached.
|
||||
if (queryType == dns.TypeA || queryType == dns.TypeAAAA) && r.backend.NdotsSet() &&
|
||||
!strings.Contains(strings.TrimSuffix(queryName, "."), ".") {
|
||||
resp = createRespMsg(query)
|
||||
} else {
|
||||
resp = r.forwardExtDNS(ctx, w.LocalAddr().Network(), w.RemoteAddr(), query)
|
||||
}
|
||||
|
||||
if resp == nil {
|
||||
@@ -530,10 +539,18 @@ func (r *Resolver) forwardExtDNS(ctx context.Context, proto string, remoteAddr n
|
||||
ctx, span := otel.Tracer("").Start(ctx, "resolver.forwardExtDNS")
|
||||
defer span.End()
|
||||
|
||||
proxyDNS := r.proxyDNS.Load()
|
||||
for _, extDNS := range r.extDNS(netiputil.AddrPortFromNet(remoteAddr)) {
|
||||
if extDNS.IPStr == "" {
|
||||
break
|
||||
}
|
||||
// If proxyDNS is false, do not forward the request from the host's namespace
|
||||
// (don't access an external DNS server from an internal network). But, it is
|
||||
// safe to make the request from the container's network namespace - it'll fail
|
||||
// if the DNS server is not accessible, but the server may be on-net.
|
||||
if !proxyDNS && extDNS.HostLoopback {
|
||||
continue
|
||||
}
|
||||
|
||||
// limits the number of outstanding concurrent queries.
|
||||
ctx, cancel := context.WithTimeout(ctx, extIOTimeout)
|
||||
|
||||
@@ -25,6 +25,10 @@ profile {{.Name}} flags=(attach_disconnected,mediate_deleted) {
|
||||
umount,
|
||||
# Host (privileged) processes may send signals to container processes.
|
||||
signal (receive) peer=unconfined,
|
||||
# runc may send signals to container processes (for "docker stop").
|
||||
signal (receive) peer=runc,
|
||||
# crun may send signals to container processes (for "docker stop" when used with crun OCI runtime).
|
||||
signal (receive) peer=crun,
|
||||
# dockerd may send signals to container processes (for "docker kill").
|
||||
signal (receive) peer={{.DaemonProfile}},
|
||||
# Container processes may send signals amongst themselves.
|
||||
|
||||
@@ -25,7 +25,7 @@ require (
|
||||
github.com/aws/smithy-go v1.19.0
|
||||
github.com/cloudflare/cfssl v1.6.4
|
||||
github.com/containerd/cgroups/v3 v3.0.3
|
||||
github.com/containerd/containerd v1.7.15
|
||||
github.com/containerd/containerd v1.7.16
|
||||
github.com/containerd/continuity v0.4.3
|
||||
github.com/containerd/fifo v1.1.0
|
||||
github.com/containerd/log v0.1.0
|
||||
@@ -60,7 +60,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.13.1
|
||||
github.com/moby/buildkit v0.13.2
|
||||
github.com/moby/docker-image-spec v1.3.1
|
||||
github.com/moby/ipvs v1.1.0
|
||||
github.com/moby/locker v1.0.1
|
||||
@@ -87,7 +87,7 @@ require (
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.0
|
||||
github.com/spf13/pflag v1.0.5
|
||||
github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5
|
||||
github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c
|
||||
github.com/tonistiigi/go-archvariant v1.0.0
|
||||
github.com/vbatts/tar-split v0.11.5
|
||||
github.com/vishvananda/netlink v1.2.1-beta.2
|
||||
@@ -110,7 +110,7 @@ require (
|
||||
google.golang.org/protobuf v1.33.0
|
||||
gotest.tools/v3 v3.5.1
|
||||
resenje.org/singleflight v0.4.1
|
||||
tags.cncf.io/container-device-interface v0.7.1
|
||||
tags.cncf.io/container-device-interface v0.7.2
|
||||
)
|
||||
|
||||
require (
|
||||
|
||||
16
vendor.sum
16
vendor.sum
@@ -156,8 +156,8 @@ github.com/containerd/cgroups/v3 v3.0.3 h1:S5ByHZ/h9PMe5IOQoN7E+nMc2UcLEM/V48DGD
|
||||
github.com/containerd/cgroups/v3 v3.0.3/go.mod h1:8HBe7V3aWGLFPd/k03swSIsGjZhHI2WzJmticMgVuz0=
|
||||
github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro=
|
||||
github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk=
|
||||
github.com/containerd/containerd v1.7.15 h1:afEHXdil9iAm03BmhjzKyXnnEBtjaLJefdU7DV0IFes=
|
||||
github.com/containerd/containerd v1.7.15/go.mod h1:ISzRRTMF8EXNpJlTzyr2XMhN+j9K302C21/+cr3kUnY=
|
||||
github.com/containerd/containerd v1.7.16 h1:7Zsfe8Fkj4Wi2My6DXGQ87hiqIrmOXolm72ZEkFU5Mg=
|
||||
github.com/containerd/containerd v1.7.16/go.mod h1:NL49g7A/Fui7ccmxV6zkBWwqMgmMxFWzujYCc+JLt7k=
|
||||
github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8=
|
||||
github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
|
||||
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
|
||||
@@ -478,8 +478,8 @@ github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh
|
||||
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.13.1 h1:L8afOFhPq2RPJJSr/VyzbufwID7jquZVB7oFHbPRcPE=
|
||||
github.com/moby/buildkit v0.13.1/go.mod h1:aNmNQKLBFYAOFuzQjR3VA27/FijlvtBD1pjNwTSN37k=
|
||||
github.com/moby/buildkit v0.13.2 h1:nXNszM4qD9E7QtG7bFWPnDI1teUQFQglBzon/IU3SzI=
|
||||
github.com/moby/buildkit v0.13.2/go.mod h1:2cyVOv9NoHM7arphK9ZfHIWKn9YVZRFd1wXB8kKmEzY=
|
||||
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=
|
||||
@@ -673,8 +673,8 @@ 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/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tmc/grpc-websocket-proxy v0.0.0-20201229170055-e5319fda7802/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5 h1:oZS8KCqAg62sxJkEq/Ppzqrb6EooqzWtL8Oaex7bc5c=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5/go.mod h1:vbbYqJlnswsbJqWUcJN8fKtBhnEgldDrcagTgnBVKKM=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c h1:+6wg/4ORAbnSoGDzg2Q1i3CeMcT/jjhye/ZfnBHy7/M=
|
||||
github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c/go.mod h1:vbbYqJlnswsbJqWUcJN8fKtBhnEgldDrcagTgnBVKKM=
|
||||
github.com/tonistiigi/go-actions-cache v0.0.0-20240227172821-a0b64f338598 h1:DA/NDC0YbMdnfcOSUzAnbUZE6dSM54d+0hrBqG+bOfs=
|
||||
github.com/tonistiigi/go-actions-cache v0.0.0-20240227172821-a0b64f338598/go.mod h1:anhKd3mnC1shAbQj1Q4IJ+w6xqezxnyDYlx/yKa7IXM=
|
||||
github.com/tonistiigi/go-archvariant v1.0.0 h1:5LC1eDWiBNflnTF1prCiX09yfNHIxDC/aukdhCdTyb0=
|
||||
@@ -1106,7 +1106,7 @@ rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8
|
||||
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
|
||||
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
|
||||
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=
|
||||
tags.cncf.io/container-device-interface v0.7.1 h1:MATNCbAD1su9U6zwQe5BrQ2vGGp1GBayD70bYaxYCNE=
|
||||
tags.cncf.io/container-device-interface v0.7.1/go.mod h1:h1JVuOqTQVORp8DziaWKUCDNzAmN+zeCbqbqD30D0ZQ=
|
||||
tags.cncf.io/container-device-interface v0.7.2 h1:MLqGnWfOr1wB7m08ieI4YJ3IoLKKozEnnNYBtacDPQU=
|
||||
tags.cncf.io/container-device-interface v0.7.2/go.mod h1:Xb1PvXv2BhfNb3tla4r9JL129ck1Lxv9KuU6eVOfKto=
|
||||
tags.cncf.io/container-device-interface/specs-go v0.7.0 h1:w/maMGVeLP6TIQJVYT5pbqTi8SCw/iHZ+n4ignuGHqg=
|
||||
tags.cncf.io/container-device-interface/specs-go v0.7.0/go.mod h1:hMAwAbMZyBLdmYqWgYcKH0F/yctNpV3P35f+/088A80=
|
||||
|
||||
3
vendor/github.com/containerd/containerd/RELEASES.md
generated
vendored
3
vendor/github.com/containerd/containerd/RELEASES.md
generated
vendored
@@ -394,6 +394,9 @@ The deprecated properties in [`config.toml`](./docs/cri/config.md) are shown in
|
||||
|`[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**
|
||||
>
|
||||
|
||||
2
vendor/github.com/containerd/containerd/Vagrantfile
generated
vendored
2
vendor/github.com/containerd/containerd/Vagrantfile
generated
vendored
@@ -102,7 +102,7 @@ EOF
|
||||
config.vm.provision "install-golang", type: "shell", run: "once" do |sh|
|
||||
sh.upload_path = "/tmp/vagrant-install-golang"
|
||||
sh.env = {
|
||||
'GO_VERSION': ENV['GO_VERSION'] || "1.21.8",
|
||||
'GO_VERSION': ENV['GO_VERSION'] || "1.21.9",
|
||||
}
|
||||
sh.inline = <<~SHELL
|
||||
#!/usr/bin/env bash
|
||||
|
||||
8
vendor/github.com/containerd/containerd/pkg/deprecation/deprecation.go
generated
vendored
8
vendor/github.com/containerd/containerd/pkg/deprecation/deprecation.go
generated
vendored
@@ -53,6 +53,10 @@ const (
|
||||
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{
|
||||
@@ -82,6 +86,10 @@ var messages = map[Warning]string{
|
||||
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
|
||||
|
||||
4
vendor/github.com/containerd/containerd/plugin/plugin.go
generated
vendored
4
vendor/github.com/containerd/containerd/plugin/plugin.go
generated
vendored
@@ -104,6 +104,10 @@ const (
|
||||
DeprecationsPlugin = "deprecations"
|
||||
)
|
||||
|
||||
const (
|
||||
SnapshotterRootDir = "root"
|
||||
)
|
||||
|
||||
// Registration contains information for registering a plugin
|
||||
type Registration struct {
|
||||
// Type of the plugin
|
||||
|
||||
18
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
18
vendor/github.com/containerd/containerd/remotes/docker/authorizer.go
generated
vendored
@@ -148,9 +148,11 @@ func (a *dockerAuthorizer) AddResponses(ctx context.Context, responses []*http.R
|
||||
defer a.mu.Unlock()
|
||||
for _, c := range auth.ParseAuthHeader(last.Header) {
|
||||
if c.Scheme == auth.BearerAuth {
|
||||
if err := invalidAuthorization(c, responses); err != nil {
|
||||
if retry, err := invalidAuthorization(ctx, c, responses); err != nil {
|
||||
delete(a.handlers, host)
|
||||
return err
|
||||
} else if retry {
|
||||
delete(a.handlers, host)
|
||||
}
|
||||
|
||||
// reuse existing handler
|
||||
@@ -328,18 +330,24 @@ func (ah *authHandler) doBearerAuth(ctx context.Context) (token, refreshToken st
|
||||
return resp.Token, resp.RefreshToken, nil
|
||||
}
|
||||
|
||||
func invalidAuthorization(c auth.Challenge, responses []*http.Response) error {
|
||||
func invalidAuthorization(ctx context.Context, c auth.Challenge, responses []*http.Response) (retry bool, _ error) {
|
||||
errStr := c.Parameters["error"]
|
||||
if errStr == "" {
|
||||
return nil
|
||||
return retry, nil
|
||||
}
|
||||
|
||||
n := len(responses)
|
||||
if n == 1 || (n > 1 && !sameRequest(responses[n-2].Request, responses[n-1].Request)) {
|
||||
return nil
|
||||
limitedErr := errStr
|
||||
errLenghLimit := 64
|
||||
if len(limitedErr) > errLenghLimit {
|
||||
limitedErr = limitedErr[:errLenghLimit] + "..."
|
||||
}
|
||||
log.G(ctx).WithField("error", limitedErr).Debug("authorization error using bearer token, retrying")
|
||||
return true, nil
|
||||
}
|
||||
|
||||
return fmt.Errorf("server message: %s: %w", errStr, ErrInvalidAuthorization)
|
||||
return retry, fmt.Errorf("server message: %s: %w", errStr, ErrInvalidAuthorization)
|
||||
}
|
||||
|
||||
func sameRequest(r1, r2 *http.Request) bool {
|
||||
|
||||
70
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
70
vendor/github.com/containerd/containerd/remotes/docker/resolver.go
generated
vendored
@@ -704,9 +704,71 @@ func IsLocalhost(host string) bool {
|
||||
return ip.IsLoopback()
|
||||
}
|
||||
|
||||
// NewHTTPFallback returns http.RoundTripper which allows fallback from https to
|
||||
// http for registry endpoints with configurations for both http and TLS,
|
||||
// such as defaulted localhost endpoints.
|
||||
func NewHTTPFallback(transport http.RoundTripper) http.RoundTripper {
|
||||
return &httpFallback{
|
||||
super: transport,
|
||||
}
|
||||
}
|
||||
|
||||
type httpFallback struct {
|
||||
super http.RoundTripper
|
||||
host string
|
||||
}
|
||||
|
||||
func (f *httpFallback) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
// only fall back if the same host had previously fell back
|
||||
if f.host != r.URL.Host {
|
||||
resp, err := f.super.RoundTrip(r)
|
||||
if !isTLSError(err) {
|
||||
return resp, err
|
||||
}
|
||||
}
|
||||
|
||||
plainHTTPUrl := *r.URL
|
||||
plainHTTPUrl.Scheme = "http"
|
||||
|
||||
plainHTTPRequest := *r
|
||||
plainHTTPRequest.URL = &plainHTTPUrl
|
||||
|
||||
if f.host != r.URL.Host {
|
||||
f.host = r.URL.Host
|
||||
|
||||
// update body on the second attempt
|
||||
if r.Body != nil && r.GetBody != nil {
|
||||
body, err := r.GetBody()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
plainHTTPRequest.Body = body
|
||||
}
|
||||
}
|
||||
|
||||
return f.super.RoundTrip(&plainHTTPRequest)
|
||||
}
|
||||
|
||||
func isTLSError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
var tlsErr tls.RecordHeaderError
|
||||
if errors.As(err, &tlsErr) && string(tlsErr.RecordHeader[:]) == "HTTP/" {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(err.Error(), "TLS handshake timeout") {
|
||||
return true
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
@@ -722,6 +784,14 @@ func (f HTTPFallback) RoundTrip(r *http.Request) (*http.Response, error) {
|
||||
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)
|
||||
}
|
||||
|
||||
|
||||
18
vendor/github.com/containerd/containerd/services/server/config/config.go
generated
vendored
18
vendor/github.com/containerd/containerd/services/server/config/config.go
generated
vendored
@@ -164,8 +164,10 @@ type CgroupConfig struct {
|
||||
|
||||
// ProxyPlugin provides a proxy plugin configuration
|
||||
type ProxyPlugin struct {
|
||||
Type string `toml:"type"`
|
||||
Address string `toml:"address"`
|
||||
Type string `toml:"type"`
|
||||
Address string `toml:"address"`
|
||||
Platform string `toml:"platform"`
|
||||
Exports map[string]string `toml:"exports"`
|
||||
}
|
||||
|
||||
// Decode unmarshals a plugin specific configuration by plugin id
|
||||
@@ -251,13 +253,18 @@ func loadConfigFile(path string) (*Config, error) {
|
||||
}
|
||||
|
||||
// resolveImports resolves import strings list to absolute paths list:
|
||||
// - If path contains *, glob pattern matching applied
|
||||
// - Non abs path is relative to parent config file directory
|
||||
// - If path contains *, glob pattern matching applied
|
||||
// - Abs paths returned as is
|
||||
func resolveImports(parent string, imports []string) ([]string, error) {
|
||||
var out []string
|
||||
|
||||
for _, path := range imports {
|
||||
path := filepath.Clean(path)
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(filepath.Dir(parent), path)
|
||||
}
|
||||
|
||||
if strings.Contains(path, "*") {
|
||||
matches, err := filepath.Glob(path)
|
||||
if err != nil {
|
||||
@@ -266,11 +273,6 @@ func resolveImports(parent string, imports []string) ([]string, error) {
|
||||
|
||||
out = append(out, matches...)
|
||||
} else {
|
||||
path = filepath.Clean(path)
|
||||
if !filepath.IsAbs(path) {
|
||||
path = filepath.Join(filepath.Dir(parent), path)
|
||||
}
|
||||
|
||||
out = append(out, path)
|
||||
}
|
||||
}
|
||||
|
||||
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
2
vendor/github.com/containerd/containerd/version/version.go
generated
vendored
@@ -23,7 +23,7 @@ var (
|
||||
Package = "github.com/containerd/containerd"
|
||||
|
||||
// Version holds the complete version number. Filled in at linking time.
|
||||
Version = "1.7.15+unknown"
|
||||
Version = "1.7.16+unknown"
|
||||
|
||||
// Revision is filled with the VCS (e.g. git) revision being used to build
|
||||
// the program at linking time.
|
||||
|
||||
9
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
generated
vendored
9
vendor/github.com/moby/buildkit/cmd/buildkitd/config/config.go
generated
vendored
@@ -40,10 +40,11 @@ type LogConfig struct {
|
||||
}
|
||||
|
||||
type GRPCConfig struct {
|
||||
Address []string `toml:"address"`
|
||||
DebugAddress string `toml:"debugAddress"`
|
||||
UID *int `toml:"uid"`
|
||||
GID *int `toml:"gid"`
|
||||
Address []string `toml:"address"`
|
||||
DebugAddress string `toml:"debugAddress"`
|
||||
UID *int `toml:"uid"`
|
||||
GID *int `toml:"gid"`
|
||||
SecurityDescriptor string `toml:"securityDescriptor"`
|
||||
|
||||
TLS TLSConfig `toml:"tls"`
|
||||
// MaxRecvMsgSize int `toml:"max_recv_message_size"`
|
||||
|
||||
23
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy.go
generated
vendored
23
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy.go
generated
vendored
@@ -7,6 +7,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/docker/go-units"
|
||||
"github.com/moby/buildkit/util/bklog"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
@@ -104,3 +105,25 @@ func stripQuotes(s string) string {
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func DetectDefaultGCCap() DiskSpace {
|
||||
return DiskSpace{Percentage: DiskSpacePercentage}
|
||||
}
|
||||
|
||||
func (d DiskSpace) AsBytes(root string) int64 {
|
||||
if d.Bytes != 0 {
|
||||
return d.Bytes
|
||||
}
|
||||
if d.Percentage == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
diskSize, err := getDiskSize(root)
|
||||
if err != nil {
|
||||
bklog.L.Warnf("failed to get disk size: %v", err)
|
||||
return defaultCap
|
||||
}
|
||||
avail := diskSize * d.Percentage / 100
|
||||
rounded := (avail/(1<<30) + 1) * 1e9 // round up
|
||||
return rounded
|
||||
}
|
||||
|
||||
18
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_unix.go
generated
vendored
18
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_unix.go
generated
vendored
@@ -7,23 +7,13 @@ import (
|
||||
"syscall"
|
||||
)
|
||||
|
||||
func DetectDefaultGCCap() DiskSpace {
|
||||
return DiskSpace{Percentage: 10}
|
||||
}
|
||||
|
||||
func (d DiskSpace) AsBytes(root string) int64 {
|
||||
if d.Bytes != 0 {
|
||||
return d.Bytes
|
||||
}
|
||||
if d.Percentage == 0 {
|
||||
return 0
|
||||
}
|
||||
var DiskSpacePercentage int64 = 10
|
||||
|
||||
func getDiskSize(root string) (int64, error) {
|
||||
var st syscall.Statfs_t
|
||||
if err := syscall.Statfs(root, &st); err != nil {
|
||||
return defaultCap
|
||||
return 0, err
|
||||
}
|
||||
diskSize := int64(st.Bsize) * int64(st.Blocks)
|
||||
avail := diskSize * d.Percentage / 100
|
||||
return (avail/(1<<30) + 1) * 1e9 // round up
|
||||
return diskSize, nil
|
||||
}
|
||||
|
||||
29
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_windows.go
generated
vendored
29
vendor/github.com/moby/buildkit/cmd/buildkitd/config/gcpolicy_windows.go
generated
vendored
@@ -3,10 +3,29 @@
|
||||
|
||||
package config
|
||||
|
||||
func DetectDefaultGCCap() DiskSpace {
|
||||
return DiskSpace{Bytes: defaultCap}
|
||||
}
|
||||
import (
|
||||
"golang.org/x/sys/windows"
|
||||
)
|
||||
|
||||
func (d DiskSpace) AsBytes(root string) int64 {
|
||||
return d.Bytes
|
||||
// set as double that for Linux since
|
||||
// Windows images are generally larger.
|
||||
var DiskSpacePercentage int64 = 20
|
||||
|
||||
func getDiskSize(root string) (int64, error) {
|
||||
rootUTF16, err := windows.UTF16FromString(root)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
var freeAvailableBytes uint64
|
||||
var totalBytes uint64
|
||||
var totalFreeBytes uint64
|
||||
|
||||
if err := windows.GetDiskFreeSpaceEx(
|
||||
&rootUTF16[0],
|
||||
&freeAvailableBytes,
|
||||
&totalBytes,
|
||||
&totalFreeBytes); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return int64(totalBytes), nil
|
||||
}
|
||||
|
||||
13
vendor/github.com/moby/buildkit/exporter/containerimage/writer.go
generated
vendored
13
vendor/github.com/moby/buildkit/exporter/containerimage/writer.go
generated
vendored
@@ -419,11 +419,16 @@ func (ic *ImageWriter) rewriteRemoteWithEpoch(ctx context.Context, opts *ImageCo
|
||||
var divergedFromBase bool
|
||||
for i, desc := range remoteDescriptors {
|
||||
i, desc := i, desc
|
||||
info, err := cs.Info(ctx, desc.Digest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Usually we get non-empty diffID here, but if the content was ingested via a third-party containerd client,
|
||||
// diffID here can be empty, and will be computed by the converter.
|
||||
diffID := digest.Digest(desc.Annotations[labels.LabelUncompressed])
|
||||
if diffID == "" {
|
||||
info, err := cs.Info(ctx, desc.Digest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
diffID = digest.Digest(info.Labels[labels.LabelUncompressed]) // can be still empty
|
||||
}
|
||||
diffID := digest.Digest(info.Labels[labels.LabelUncompressed]) // can be empty
|
||||
var immDiffID digest.Digest
|
||||
if !divergedFromBase && baseImg != nil && i < len(baseImg.RootFS.DiffIDs) {
|
||||
immDiffID = baseImg.RootFS.DiffIDs[i]
|
||||
|
||||
5
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
generated
vendored
5
vendor/github.com/moby/buildkit/frontend/dockerfile/dockerfile2llb/convert.go
generated
vendored
@@ -1340,11 +1340,10 @@ func dispatchCopy(d *dispatchState, cfg copyConfig) error {
|
||||
copyOpts := []llb.ConstraintsOpt{
|
||||
llb.Platform(*d.platform),
|
||||
}
|
||||
copy(copyOpts, fileOpt)
|
||||
copyOpts = append(copyOpts, fileOpt...)
|
||||
copyOpts = append(copyOpts, llb.ProgressGroup(pgID, pgName, true))
|
||||
|
||||
var mergeOpts []llb.ConstraintsOpt
|
||||
copy(mergeOpts, fileOpt)
|
||||
mergeOpts := append([]llb.ConstraintsOpt{}, fileOpt...)
|
||||
d.cmdIndex--
|
||||
mergeOpts = append(mergeOpts, llb.ProgressGroup(pgID, pgName, false), llb.WithCustomName(prefixCommand(d, "LINK "+name, d.prefixPlatform, &platform, env)))
|
||||
|
||||
|
||||
10
vendor/github.com/moby/buildkit/util/converter/tarconverter/tarconverter.go
generated
vendored
10
vendor/github.com/moby/buildkit/util/converter/tarconverter/tarconverter.go
generated
vendored
@@ -8,6 +8,7 @@ import (
|
||||
type HeaderConverter func(*tar.Header)
|
||||
|
||||
// NewReader returns a reader that applies headerConverter.
|
||||
// srcContent is drained until hitting EOF.
|
||||
// Forked from https://github.com/moby/moby/blob/v24.0.6/pkg/archive/copy.go#L308-L373 .
|
||||
func NewReader(srcContent io.Reader, headerConverter HeaderConverter) io.ReadCloser {
|
||||
rebased, w := io.Pipe()
|
||||
@@ -21,7 +22,14 @@ func NewReader(srcContent io.Reader, headerConverter HeaderConverter) io.ReadClo
|
||||
if err == io.EOF {
|
||||
// Signals end of archive.
|
||||
rebasedTar.Close()
|
||||
w.Close()
|
||||
// drain the reader into io.Discard, until hitting EOF
|
||||
// https://github.com/moby/buildkit/pull/4807#discussion_r1544621787
|
||||
_, err = io.Copy(io.Discard, srcContent)
|
||||
if err != nil {
|
||||
w.CloseWithError(err)
|
||||
} else {
|
||||
w.Close()
|
||||
}
|
||||
return
|
||||
}
|
||||
if err != nil {
|
||||
|
||||
2
vendor/github.com/tonistiigi/fsutil/diff_containerd.go
generated
vendored
2
vendor/github.com/tonistiigi/fsutil/diff_containerd.go
generated
vendored
@@ -111,7 +111,7 @@ func doubleWalkDiff(ctx context.Context, changeFn ChangeFunc, a, b walkerFn, fil
|
||||
if filter != nil {
|
||||
filter(f2.path, &statCopy)
|
||||
}
|
||||
f2copy = ¤tPath{path: filepath.FromSlash(f2.path), stat: &statCopy}
|
||||
f2copy = ¤tPath{path: f2.path, stat: &statCopy}
|
||||
}
|
||||
k, p := pathChange(f1, f2copy)
|
||||
switch k {
|
||||
|
||||
20
vendor/github.com/tonistiigi/fsutil/diskwriter.go
generated
vendored
20
vendor/github.com/tonistiigi/fsutil/diskwriter.go
generated
vendored
@@ -37,6 +37,7 @@ type DiskWriter struct {
|
||||
ctx context.Context
|
||||
cancel func()
|
||||
eg *errgroup.Group
|
||||
egCtx context.Context
|
||||
filter FilterFunc
|
||||
dirModTimes map[string]int64
|
||||
}
|
||||
@@ -50,13 +51,14 @@ func NewDiskWriter(ctx context.Context, dest string, opt DiskWriterOpt) (*DiskWr
|
||||
}
|
||||
|
||||
ctx, cancel := context.WithCancel(ctx)
|
||||
eg, ctx := errgroup.WithContext(ctx)
|
||||
eg, egCtx := errgroup.WithContext(ctx)
|
||||
|
||||
return &DiskWriter{
|
||||
opt: opt,
|
||||
dest: dest,
|
||||
eg: eg,
|
||||
ctx: ctx,
|
||||
egCtx: egCtx,
|
||||
cancel: cancel,
|
||||
filter: opt.Filter,
|
||||
dirModTimes: map[string]int64{},
|
||||
@@ -98,7 +100,7 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
|
||||
}
|
||||
}()
|
||||
|
||||
destPath := filepath.Join(dw.dest, filepath.FromSlash(p))
|
||||
destPath := filepath.Join(dw.dest, p)
|
||||
|
||||
if kind == ChangeKindDelete {
|
||||
if dw.filter != nil {
|
||||
@@ -183,12 +185,12 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
|
||||
}
|
||||
default:
|
||||
isRegularFile = true
|
||||
file, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY, fi.Mode()) //todo: windows
|
||||
file, err := os.OpenFile(newPath, os.O_CREATE|os.O_WRONLY, fi.Mode())
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "failed to create %s", newPath)
|
||||
}
|
||||
if dw.opt.SyncDataCb != nil {
|
||||
if err := dw.processChange(ChangeKindAdd, p, fi, file); err != nil {
|
||||
if err := dw.processChange(dw.ctx, ChangeKindAdd, p, fi, file); err != nil {
|
||||
file.Close()
|
||||
return err
|
||||
}
|
||||
@@ -219,7 +221,7 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
|
||||
dw.requestAsyncFileData(p, destPath, fi, &statCopy)
|
||||
}
|
||||
} else {
|
||||
return dw.processChange(kind, p, fi, nil)
|
||||
return dw.processChange(dw.ctx, kind, p, fi, nil)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -228,7 +230,7 @@ func (dw *DiskWriter) HandleChange(kind ChangeKind, p string, fi os.FileInfo, er
|
||||
func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo, st *types.Stat) {
|
||||
// todo: limit worker threads
|
||||
dw.eg.Go(func() error {
|
||||
if err := dw.processChange(ChangeKindAdd, p, fi, &lazyFileWriter{
|
||||
if err := dw.processChange(dw.egCtx, ChangeKindAdd, p, fi, &lazyFileWriter{
|
||||
dest: dest,
|
||||
}); err != nil {
|
||||
return err
|
||||
@@ -237,7 +239,7 @@ func (dw *DiskWriter) requestAsyncFileData(p, dest string, fi os.FileInfo, st *t
|
||||
})
|
||||
}
|
||||
|
||||
func (dw *DiskWriter) processChange(kind ChangeKind, p string, fi os.FileInfo, w io.WriteCloser) error {
|
||||
func (dw *DiskWriter) processChange(ctx context.Context, kind ChangeKind, p string, fi os.FileInfo, w io.WriteCloser) error {
|
||||
origw := w
|
||||
var hw *hashedWriter
|
||||
if dw.opt.NotifyCb != nil {
|
||||
@@ -252,7 +254,7 @@ func (dw *DiskWriter) processChange(kind ChangeKind, p string, fi os.FileInfo, w
|
||||
if fn == nil && dw.opt.AsyncDataCb != nil {
|
||||
fn = dw.opt.AsyncDataCb
|
||||
}
|
||||
if err := fn(dw.ctx, p, w); err != nil {
|
||||
if err := fn(ctx, p, w); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -313,7 +315,7 @@ type lazyFileWriter struct {
|
||||
|
||||
func (lfw *lazyFileWriter) Write(dt []byte) (int, error) {
|
||||
if lfw.f == nil {
|
||||
file, err := os.OpenFile(lfw.dest, os.O_WRONLY, 0) //todo: windows
|
||||
file, err := os.OpenFile(lfw.dest, os.O_WRONLY, 0)
|
||||
if os.IsPermission(err) {
|
||||
// retry after chmod
|
||||
fi, er := os.Stat(lfw.dest)
|
||||
|
||||
68
vendor/github.com/tonistiigi/fsutil/hardlinks.go
generated
vendored
68
vendor/github.com/tonistiigi/fsutil/hardlinks.go
generated
vendored
@@ -1,6 +1,9 @@
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
gofs "io/fs"
|
||||
"os"
|
||||
"syscall"
|
||||
|
||||
@@ -46,3 +49,68 @@ func (v *Hardlinks) HandleChange(kind ChangeKind, p string, fi os.FileInfo, err
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// WithHardlinkReset returns a FS that fixes hardlinks for FS that has been filtered
|
||||
// so that original hardlink sources might be missing
|
||||
func WithHardlinkReset(fs FS) FS {
|
||||
return &hardlinkFilter{fs: fs}
|
||||
}
|
||||
|
||||
type hardlinkFilter struct {
|
||||
fs FS
|
||||
}
|
||||
|
||||
var _ FS = &hardlinkFilter{}
|
||||
|
||||
func (r *hardlinkFilter) Walk(ctx context.Context, target string, fn gofs.WalkDirFunc) error {
|
||||
seenFiles := make(map[string]string)
|
||||
return r.fs.Walk(ctx, target, func(path string, entry gofs.DirEntry, err error) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fi, err := entry.Info()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if fi.IsDir() || fi.Mode()&os.ModeSymlink != 0 {
|
||||
return fn(path, entry, nil)
|
||||
}
|
||||
|
||||
stat, ok := fi.Sys().(*types.Stat)
|
||||
if !ok {
|
||||
return errors.WithStack(&os.PathError{Path: path, Err: syscall.EBADMSG, Op: "fileinfo without stat info"})
|
||||
}
|
||||
|
||||
if stat.Linkname != "" {
|
||||
if v, ok := seenFiles[stat.Linkname]; !ok {
|
||||
seenFiles[stat.Linkname] = stat.Path
|
||||
stat.Linkname = ""
|
||||
entry = &dirEntryWithStat{DirEntry: entry, stat: stat}
|
||||
} else {
|
||||
if v != stat.Path {
|
||||
stat.Linkname = v
|
||||
entry = &dirEntryWithStat{DirEntry: entry, stat: stat}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
seenFiles[path] = stat.Path
|
||||
|
||||
return fn(path, entry, nil)
|
||||
})
|
||||
}
|
||||
|
||||
func (r *hardlinkFilter) Open(p string) (io.ReadCloser, error) {
|
||||
return r.fs.Open(p)
|
||||
}
|
||||
|
||||
type dirEntryWithStat struct {
|
||||
gofs.DirEntry
|
||||
stat *types.Stat
|
||||
}
|
||||
|
||||
func (d *dirEntryWithStat) Info() (gofs.FileInfo, error) {
|
||||
return &StatInfo{d.stat}, nil
|
||||
}
|
||||
|
||||
45
vendor/github.com/tonistiigi/fsutil/receive.go
generated
vendored
45
vendor/github.com/tonistiigi/fsutil/receive.go
generated
vendored
@@ -1,10 +1,42 @@
|
||||
// send.go and receive.go describe the fsutil file-transfer protocol, which
|
||||
// allows transferring file trees across a network connection.
|
||||
//
|
||||
// The protocol operates as follows:
|
||||
// - The client (the receiver) connects to the server (the sender).
|
||||
// - The sender walks the target tree lexicographically and sends a series of
|
||||
// STAT packets that describe each file (an empty stat indicates EOF).
|
||||
// - The receiver sends a REQ packet for each file it requires the contents for,
|
||||
// using the ID for the file (determined as its index in the STAT sequence).
|
||||
// - The sender sends a DATA packet with byte arrays for the contents of the
|
||||
// file, associated with an ID (an empty array indicates EOF).
|
||||
// - Once the receiver has received all files it wants, it sends a FIN packet,
|
||||
// and the file transfer is complete.
|
||||
// If an error is encountered on either side, an ERR packet is sent containing
|
||||
// a human-readable error.
|
||||
//
|
||||
// All paths transferred over the protocol are normalized to unix-style paths,
|
||||
// regardless of which platforms are present on either side. These path
|
||||
// conversions are performed right before sending a STAT packet (for the
|
||||
// sender) or right after receiving the corresponding STAT packet (for the
|
||||
// receiver); this abstraction doesn't leak into the rest of fsutil, which
|
||||
// operates on native platform-specific paths.
|
||||
//
|
||||
// Note that in the case of cross-platform file transfers, the transfer is
|
||||
// best-effort. Some filenames that are valid on a unix sender would not be
|
||||
// valid on a windows receiver, so these paths are rejected as they are
|
||||
// received. Additionally, file metadata, like user/group owners and xattrs do
|
||||
// not have an exact correspondence on windows, and so would be discarded by
|
||||
// a windows receiver.
|
||||
|
||||
package fsutil
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"syscall"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/tonistiigi/fsutil/types"
|
||||
@@ -184,13 +216,24 @@ func (r *receiver) run(ctx context.Context) error {
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
// normalize unix wire-specific paths to platform-specific paths
|
||||
path := filepath.FromSlash(p.Stat.Path)
|
||||
if filepath.ToSlash(path) != p.Stat.Path {
|
||||
// e.g. a linux path foo/bar\baz cannot be represented on windows
|
||||
return errors.WithStack(&os.PathError{Path: p.Stat.Path, Err: syscall.EINVAL, Op: "unrepresentable path"})
|
||||
}
|
||||
p.Stat.Path = path
|
||||
p.Stat.Linkname = filepath.FromSlash(p.Stat.Linkname)
|
||||
|
||||
if fileCanRequestData(os.FileMode(p.Stat.Mode)) {
|
||||
r.mu.Lock()
|
||||
r.files[p.Stat.Path] = i
|
||||
r.mu.Unlock()
|
||||
}
|
||||
i++
|
||||
cp := ¤tPath{path: p.Stat.Path, stat: p.Stat}
|
||||
|
||||
cp := ¤tPath{path: path, stat: p.Stat}
|
||||
if err := r.orderValidator.HandleChange(ChangeKindAdd, cp.path, &StatInfo{cp.stat}, nil); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
3
vendor/github.com/tonistiigi/fsutil/send.go
generated
vendored
3
vendor/github.com/tonistiigi/fsutil/send.go
generated
vendored
@@ -29,7 +29,7 @@ type Stream interface {
|
||||
func Send(ctx context.Context, conn Stream, fs FS, progressCb func(int, bool)) error {
|
||||
s := &sender{
|
||||
conn: &syncStream{Stream: conn},
|
||||
fs: fs,
|
||||
fs: WithHardlinkReset(fs),
|
||||
files: make(map[uint32]string),
|
||||
progressCb: progressCb,
|
||||
sendpipeline: make(chan *sendHandle, 128),
|
||||
@@ -161,6 +161,7 @@ func (s *sender) walk(ctx context.Context) error {
|
||||
return errors.WithStack(&os.PathError{Path: path, Err: syscall.EBADMSG, Op: "fileinfo without stat info"})
|
||||
}
|
||||
stat.Path = filepath.ToSlash(stat.Path)
|
||||
stat.Linkname = filepath.ToSlash(stat.Linkname)
|
||||
p := &types.Packet{
|
||||
Type: types.PACKET_STAT,
|
||||
Stat: stat,
|
||||
|
||||
8
vendor/modules.txt
vendored
8
vendor/modules.txt
vendored
@@ -260,7 +260,7 @@ 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.15
|
||||
# github.com/containerd/containerd v1.7.16
|
||||
## explicit; go 1.21
|
||||
github.com/containerd/containerd
|
||||
github.com/containerd/containerd/api/events
|
||||
@@ -709,7 +709,7 @@ github.com/mitchellh/hashstructure/v2
|
||||
# github.com/mitchellh/reflectwalk v1.0.2
|
||||
## explicit
|
||||
github.com/mitchellh/reflectwalk
|
||||
# github.com/moby/buildkit v0.13.1
|
||||
# github.com/moby/buildkit v0.13.2
|
||||
## explicit; go 1.21
|
||||
github.com/moby/buildkit/api/services/control
|
||||
github.com/moby/buildkit/api/types
|
||||
@@ -1086,7 +1086,7 @@ github.com/syndtr/gocapability/capability
|
||||
# github.com/tinylib/msgp v1.1.8
|
||||
## explicit; go 1.15
|
||||
github.com/tinylib/msgp/msgp
|
||||
# github.com/tonistiigi/fsutil v0.0.0-20240301111122-7525a1af2bb5
|
||||
# github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c
|
||||
## explicit; go 1.20
|
||||
github.com/tonistiigi/fsutil
|
||||
github.com/tonistiigi/fsutil/copy
|
||||
@@ -1600,7 +1600,7 @@ resenje.org/singleflight
|
||||
# sigs.k8s.io/yaml v1.3.0
|
||||
## explicit; go 1.12
|
||||
sigs.k8s.io/yaml
|
||||
# tags.cncf.io/container-device-interface v0.7.1
|
||||
# tags.cncf.io/container-device-interface v0.7.2
|
||||
## explicit; go 1.20
|
||||
tags.cncf.io/container-device-interface/internal/validation
|
||||
tags.cncf.io/container-device-interface/internal/validation/k8s
|
||||
|
||||
Reference in New Issue
Block a user