Compare commits

...

37 Commits

Author SHA1 Message Date
Justin Chadwell
b4df08551f Merge pull request #1930 from jedevc/revert-bc597e6b 2023-07-05 17:37:36 +01:00
Justin Chadwell
f581942d7d Merge pull request #1929 from jedevc/vendor-vt100-update 2023-07-05 17:37:20 +01:00
Justin Chadwell
5159571dfc Revert "bake: fix incorrect dockerfile resolution against cwd:// context"
This reverts commit bc597e6b5e.

Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-07-05 17:25:09 +01:00
Justin Chadwell
86a5c77c2b vendor: update tonistiigi/vt100 to master@f9a4f7ef6531
Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-07-05 16:47:43 +01:00
Justin Chadwell
1602b491f9 Merge pull request #1926 from jedevc/v0.11-cherry-picks 2023-07-05 13:54:12 +01:00
CrazyMax
94baaf3c90 build: fix host-gateway handling
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 8cbb7a9319)
2023-07-03 21:58:40 +02:00
CrazyMax
c5e279f295 docs: update generated content
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 87b9f9ecfb)
2023-07-03 21:58:40 +02:00
CrazyMax
a0f91eb87e vendor: update cli-docs-tool to 0.6.0
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit cbc473359a)
2023-07-03 21:58:40 +02:00
CrazyMax
cb1812ec6a test: build details output
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 20d2501edc)
2023-07-03 21:58:39 +02:00
CrazyMax
47e4c2576b build: missing newline when printing build details on error
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit d45601fdc6)
2023-07-03 21:58:39 +02:00
CrazyMax
3702e17ed5 dockerfile: update docker to 24.0.2
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 7147463418)
2023-07-03 21:58:39 +02:00
Jhan S. Álvarez
8b85dbea72 controller: include CgroupParent in build.Options
Signed-off-by: Jhan S. Álvarez <alvarezpcuser@gmail.com>
(cherry picked from commit e65f6b8c8b)
2023-07-03 11:55:40 +01:00
CrazyMax
afcb118e10 bake: ignore profiles in compose definitions
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 120f3a8918)
2023-07-03 11:55:40 +01:00
David Karlsson
cb4fea66e0 chore: make docs
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
(cherry picked from commit 1e576dd7c6)
2023-07-03 11:53:42 +01:00
CrazyMax
74fa66b496 docs: set experimental annotation
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 7a5472153b)
2023-07-03 11:53:42 +01:00
Justin Chadwell
ff87dd183a Merge pull request #1885 from crazy-max/v0.11.1_backport 2023-06-21 11:23:10 +01:00
CrazyMax
9f844df9f7 builder: skip name validation for docker context
Although a builder from the store cannot be created unless
it has a valid name, this is not the case for a Docker context.

We should skip name validation when checking a node from the
store and fall back to finding one from Docker context instead.

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit b1c5449428)
2023-06-15 14:10:24 +02:00
Justin Chadwell
bc597e6b5e bake: fix incorrect dockerfile resolution against cwd:// context
We need to resolve the strip the cwd:// prefix before attempting to
resolve the dockerfile. Otherwise, we'll get the cwd:// prefix in the
dockerfile name, which isn't stripped out later.

Signed-off-by: Justin Chadwell <me@jedevc.com>
(cherry picked from commit 431732f5d1)
2023-06-15 14:10:23 +02:00
CrazyMax
687feca9e8 Merge pull request #1877 from jedevc/cache-dockerutil-features
dockerutil: cache feature collection
2023-06-13 11:42:22 +02:00
Justin Chadwell
d4a2c8d0c3 dockerutil: cache feature collection
Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-06-13 09:47:38 +01:00
Justin Chadwell
bef42b2441 Merge pull request #1876 from tonistiigi/remove-history-request 2023-06-13 09:38:05 +01:00
CrazyMax
2de333fdd3 check history api support once
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
2023-06-13 10:29:22 +02:00
Tonis Tiigi
1138789f20 avoid extra client for history API detection
Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>
2023-06-12 17:39:09 -07:00
Justin Chadwell
1f4ac09ffb Merge pull request #1874 from thaJeztah/bump_engine_24.0.2 2023-06-09 11:39:13 +01:00
CrazyMax
26a8ffb393 Merge pull request #1873 from jedevc/vendor-buildkit-master
vendor: update buildkit to master@67a08623b95a
2023-06-09 12:14:11 +02:00
CrazyMax
9b7aada99b Merge pull request #1716 from distorhead/use-docker-cli-in-stream
build(cli): allow passing in-stream using command.Cli
2023-06-09 12:11:47 +02:00
Sebastiaan van Stijn
fd6207695b vendor: github.com/docker/cli v24.0.2
no changes in vendored files

full diff: https://github.com/docker/cli/compare/v24.0.1...v24.0.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-06-09 12:07:44 +02:00
Sebastiaan van Stijn
def96d2bf4 vendor: github.com/docker/docker v24.0.2
no changes in vendored files

full diff: https://github.com/docker/docker/compare/v24.0.1...v24.0.2

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-06-09 12:07:01 +02:00
Justin Chadwell
f5f00e68ef bake(cli): allow passing in-stream using command.Cli
ReadLocalFiles should allow passing the stdin file as an argument, which
allows us to read from dockerCli.Stdin() to be consistent with other
commands in the same package.

Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-06-09 10:50:53 +01:00
Justin Chadwell
14aebe713e debug-shell(cli): allow passing in-stream using command.Cli
Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-06-09 10:50:35 +01:00
Justin Chadwell
9d2388e6f5 vendor: update buildkit to master@67a08623b95a
Signed-off-by: Justin Chadwell <me@jedevc.com>
2023-06-09 10:36:52 +01:00
Timofey Kirillov
75e2c46295 build(cli): allow passing in-stream using command.Cli
Use command.Cli::In() which is always initialized either to os.Stdin, or to user-specified stream:
* 5be21394cb/cli/command/cli.go (L494)
* https://github.com/docker/cli/blob/master/cli/command/cli_options.go#L16C1-L26

Signed-off-by: Timofey Kirillov <timofey.kirillov@flant.com>
2023-06-09 12:19:02 +03:00
Justin Chadwell
2c02db8db4 Merge pull request #1835 from ktock/long-form-json 2023-06-08 17:10:37 +01:00
Kohei Tokunaga
e304a05d2a docs: monitor: mention about long form flag
Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2023-06-08 17:05:03 +01:00
Kohei Tokunaga
14c1ea0e11 invoke: Allow JSON array for long form flags
This commit allows specifying a JSON array to the long-form arg, entrypoint and
envvars.
Non-JSON-array value can still be specified. Buildx treats the value as a JSON
array only when it can be parsed as a JSON array.

Signed-off-by: Kohei Tokunaga <ktokunaga.mail@gmail.com>
2023-06-08 17:05:02 +01:00
Justin Chadwell
c30bcade2c Merge pull request #1870 from tianon/invoke-entrypoint-fixes 2023-06-08 16:03:24 +01:00
Tianon Gravi
62bfb19db4 Fix a couple --invoke entrypoint interaction bugs
When running `--invoke` against images that have `Cmd` set, the interactions with `Entrypoint` start to cause issues like the following:

    /usr/local/bin/bash: /usr/local/bin/bash: cannot execute binary file

Or:

    sh: can't open 'bash': No such file or directory

This patch fixes those by explicitly setting `Cmd` to be empty if it is unspecified and `Entrypoint` is being set, which matches `docker`'s behavior:

    $ docker image inspect --format '{{ json .Config.Entrypoint }} + {{ json .Config.Cmd }}' bash
    ["docker-entrypoint.sh"] + ["bash"]
    $ docker create --name foo --entrypoint bash bash
    $ docker container inspect --format '{{ json .Config.Entrypoint }} + {{ json .Config.Cmd }}' foo
    ["bash"] + null
    $ docker rm foo
    $ docker create --name foo bash ls
    $ docker container inspect --format '{{ json .Config.Entrypoint }} + {{ json .Config.Cmd }}' foo
    ["docker-entrypoint.sh"] + ["ls"]

(There are still some weird edge cases in the interaction between the `InvokeConfig` and the original image config, but this fixes the most irritating for me and the rest are going to be deeper changes that are possibly less acceptable. 😅)

Signed-off-by: Tianon Gravi <admwiggin@gmail.com>
2023-06-07 16:33:28 -07:00
50 changed files with 663 additions and 210 deletions

View File

@@ -2,13 +2,12 @@
ARG GO_VERSION=1.20 ARG GO_VERSION=1.20
ARG XX_VERSION=1.2.1 ARG XX_VERSION=1.2.1
ARG DOCKERD_VERSION=20.10.14
ARG DOCKER_VERSION=24.0.2
ARG GOTESTSUM_VERSION=v1.9.0 ARG GOTESTSUM_VERSION=v1.9.0
ARG REGISTRY_VERSION=2.8.0 ARG REGISTRY_VERSION=2.8.0
ARG BUILDKIT_VERSION=v0.11.6 ARG BUILDKIT_VERSION=v0.11.6
FROM docker:$DOCKERD_VERSION AS dockerd-release
# xx is a helper for cross-compilation # xx is a helper for cross-compilation
FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx
@@ -25,6 +24,22 @@ FROM registry:$REGISTRY_VERSION AS registry
FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit FROM moby/buildkit:$BUILDKIT_VERSION AS buildkit
FROM gobase AS docker
ARG TARGETPLATFORM
ARG DOCKER_VERSION
WORKDIR /opt/docker
RUN DOCKER_ARCH=$(case ${TARGETPLATFORM:-linux/amd64} in \
"linux/amd64") echo "x86_64" ;; \
"linux/arm/v6") echo "armel" ;; \
"linux/arm/v7") echo "armhf" ;; \
"linux/arm64") echo "aarch64" ;; \
"linux/ppc64le") echo "ppc64le" ;; \
"linux/s390x") echo "s390x" ;; \
*) echo "" ;; esac) \
&& echo "DOCKER_ARCH=$DOCKER_ARCH" \
&& wget -qO- "https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz" | tar xvz --strip 1
RUN ./dockerd --version && ./containerd --version && ./ctr --version && ./runc --version
FROM gobase AS gotestsum FROM gobase AS gotestsum
ARG GOTESTSUM_VERSION ARG GOTESTSUM_VERSION
ENV GOFLAGS= ENV GOFLAGS=
@@ -77,9 +92,20 @@ FROM binaries-$TARGETOS AS binaries
ARG BUILDKIT_SBOM_SCAN_STAGE=true ARG BUILDKIT_SBOM_SCAN_STAGE=true
FROM gobase AS integration-test-base FROM gobase AS integration-test-base
RUN apk add --no-cache docker runc containerd # https://github.com/docker/docker/blob/master/project/PACKAGERS.md#runtime-dependencies
RUN apk add --no-cache \
btrfs-progs \
e2fsprogs \
e2fsprogs-extra \
ip6tables \
iptables \
openssl \
shadow-uidmap \
xfsprogs \
xz
COPY --link --from=gotestsum /out/gotestsum /usr/bin/ COPY --link --from=gotestsum /out/gotestsum /usr/bin/
COPY --link --from=registry /bin/registry /usr/bin/ COPY --link --from=registry /bin/registry /usr/bin/
COPY --link --from=docker /opt/docker/* /usr/bin/
COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/ COPY --link --from=buildkit /usr/bin/buildkitd /usr/bin/
COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/ COPY --link --from=buildkit /usr/bin/buildctl /usr/bin/
COPY --link --from=binaries /buildx /usr/bin/ COPY --link --from=binaries /buildx /usr/bin/
@@ -102,7 +128,7 @@ FROM scratch AS release
COPY --from=releaser /out/ / COPY --from=releaser /out/ /
# Shell # Shell
FROM docker:$DOCKERD_VERSION AS dockerd-release FROM docker:$DOCKER_VERSION AS dockerd-release
FROM alpine AS shell FROM alpine AS shell
RUN apk add --no-cache iptables tmux git vim less openssh RUN apk add --no-cache iptables tmux git vim less openssh
RUN mkdir -p /usr/local/lib/docker/cli-plugins && ln -s /usr/local/bin/buildx /usr/local/lib/docker/cli-plugins/docker-buildx RUN mkdir -p /usr/local/lib/docker/cli-plugins && ln -s /usr/local/bin/buildx /usr/local/lib/docker/cli-plugins/docker-buildx

View File

@@ -55,7 +55,7 @@ func defaultFilenames() []string {
return names return names
} }
func ReadLocalFiles(names []string) ([]File, error) { func ReadLocalFiles(names []string, stdin io.Reader) ([]File, error) {
isDefault := false isDefault := false
if len(names) == 0 { if len(names) == 0 {
isDefault = true isDefault = true
@@ -67,7 +67,7 @@ func ReadLocalFiles(names []string) ([]File, error) {
var dt []byte var dt []byte
var err error var err error
if n == "-" { if n == "-" {
dt, err = io.ReadAll(os.Stdin) dt, err = io.ReadAll(stdin)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@@ -1398,7 +1398,7 @@ func TestReadLocalFilesDefault(t *testing.T) {
for _, tf := range tt.filenames { for _, tf := range tt.filenames {
require.NoError(t, os.WriteFile(tf, []byte(tf), 0644)) require.NoError(t, os.WriteFile(tf, []byte(tf), 0644))
} }
files, err := ReadLocalFiles(nil) files, err := ReadLocalFiles(nil, nil)
require.NoError(t, err) require.NoError(t, err)
if len(files) == 0 { if len(files) == 0 {
require.Equal(t, len(tt.expected), len(files)) require.Equal(t, len(tt.expected), len(files))

View File

@@ -37,6 +37,7 @@ func ParseCompose(cfgs []compose.ConfigFile, envs map[string]string) (*Config, e
}, func(options *loader.Options) { }, func(options *loader.Options) {
options.SetProjectName("bake", false) options.SetProjectName("bake", false)
options.SkipNormalization = true options.SkipNormalization = true
options.Profiles = []string{"*"}
}) })
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -36,6 +36,8 @@ services:
- token - token
- aws - aws
webapp2: webapp2:
profiles:
- test
build: build:
context: ./dir context: ./dir
dockerfile_inline: | dockerfile_inline: |

View File

@@ -642,7 +642,7 @@ func toSolveOpt(ctx context.Context, node builder.Node, multiDriver bool, opt Op
} }
// setup extrahosts // setup extrahosts
extraHosts, err := toBuildkitExtraHosts(opt.ExtraHosts, nodeDriver.IsMobyDriver()) extraHosts, err := toBuildkitExtraHosts(ctx, opt.ExtraHosts, nodeDriver)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@@ -948,7 +948,7 @@ func BuildWithResultHandler(ctx context.Context, nodes []builder.Node, opt map[s
} else { } else {
rr, err = c.Build(ctx, so, "buildx", buildFunc, ch) rr, err = c.Build(ctx, so, "buildx", buildFunc, ch)
} }
if node.Driver.Features(ctx)[driver.HistoryAPI] && desktop.BuildBackendEnabled() { if desktop.BuildBackendEnabled() && node.Driver.HistoryAPISupported(ctx) {
buildRef := fmt.Sprintf("%s/%s/%s", node.Builder, node.Name, so.Ref) buildRef := fmt.Sprintf("%s/%s/%s", node.Builder, node.Name, so.Ref)
if err != nil { if err != nil {
return &desktop.ErrorWithBuildRef{ return &desktop.ErrorWithBuildRef{
@@ -1262,7 +1262,7 @@ func createTempDockerfile(r io.Reader) (string, error) {
return dir, err return dir, err
} }
func LoadInputs(ctx context.Context, d driver.Driver, inp Inputs, pw progress.Writer, target *client.SolveOpt) (func(), error) { func LoadInputs(ctx context.Context, d *driver.DriverHandle, inp Inputs, pw progress.Writer, target *client.SolveOpt) (func(), error) {
if inp.ContextPath == "" { if inp.ContextPath == "" {
return nil, errors.New("please specify build context (e.g. \".\" for the current directory)") return nil, errors.New("please specify build context (e.g. \".\" for the current directory)")
} }

View File

@@ -13,7 +13,7 @@ import (
"github.com/pkg/errors" "github.com/pkg/errors"
) )
func createTempDockerfileFromURL(ctx context.Context, d driver.Driver, url string, pw progress.Writer) (string, error) { func createTempDockerfileFromURL(ctx context.Context, d *driver.DriverHandle, url string, pw progress.Writer) (string, error) {
c, err := driver.Boot(ctx, ctx, d, pw) c, err := driver.Boot(ctx, ctx, d, pw)
if err != nil { if err != nil {
return "", err return "", err

View File

@@ -3,10 +3,12 @@ package build
import ( import (
"archive/tar" "archive/tar"
"bytes" "bytes"
"context"
"net" "net"
"os" "os"
"strings" "strings"
"github.com/docker/buildx/driver"
"github.com/docker/cli/opts" "github.com/docker/cli/opts"
"github.com/docker/docker/builder/remotecontext/urlutil" "github.com/docker/docker/builder/remotecontext/urlutil"
"github.com/moby/buildkit/util/gitutil" "github.com/moby/buildkit/util/gitutil"
@@ -57,7 +59,7 @@ func isArchive(header []byte) bool {
} }
// toBuildkitExtraHosts converts hosts from docker key:value format to buildkit's csv format // toBuildkitExtraHosts converts hosts from docker key:value format to buildkit's csv format
func toBuildkitExtraHosts(inp []string, mobyDriver bool) (string, error) { func toBuildkitExtraHosts(ctx context.Context, inp []string, nodeDriver *driver.DriverHandle) (string, error) {
if len(inp) == 0 { if len(inp) == 0 {
return "", nil return "", nil
} }
@@ -67,11 +69,16 @@ func toBuildkitExtraHosts(inp []string, mobyDriver bool) (string, error) {
if !ok || host == "" || ip == "" { if !ok || host == "" || ip == "" {
return "", errors.Errorf("invalid host %s", h) return "", errors.Errorf("invalid host %s", h)
} }
// Skip IP address validation for "host-gateway" string with moby driver // If the IP Address is a "host-gateway", replace this value with the
if !mobyDriver || ip != mobyHostGatewayName { // IP address provided by the worker's label.
if net.ParseIP(ip) == nil { if ip == mobyHostGatewayName {
return "", errors.Errorf("invalid host %s", h) hgip, err := nodeDriver.HostGatewayIP(ctx)
if err != nil {
return "", errors.Wrap(err, "unable to derive the IP value for host-gateway")
} }
ip = hgip.String()
} else if net.ParseIP(ip) == nil {
return "", errors.Errorf("invalid host %s", h)
} }
hosts = append(hosts, host+"="+ip) hosts = append(hosts, host+"="+ip)
} }

View File

@@ -22,7 +22,7 @@ import (
type Node struct { type Node struct {
store.Node store.Node
Builder string Builder string
Driver driver.Driver Driver *driver.DriverHandle
DriverInfo *driver.Info DriverInfo *driver.Info
Platforms []ocispecs.Platform Platforms []ocispecs.Platform
GCPolicy []client.PruneInfo GCPolicy []client.PruneInfo

View File

@@ -146,7 +146,7 @@ func runBake(dockerCli command.Cli, targets []string, in bakeOptions, cFlags com
if url != "" { if url != "" {
files, inp, err = bake.ReadRemoteFiles(ctx, nodes, url, in.files, printer) files, inp, err = bake.ReadRemoteFiles(ctx, nodes, url, in.files, printer)
} else { } else {
files, err = bake.ReadLocalFiles(in.files) files, err = bake.ReadLocalFiles(in.files, dockerCli.In())
} }
if err != nil { if err != nil {
return err return err

View File

@@ -312,7 +312,7 @@ func getImageID(resp map[string]string) string {
} }
func runBasicBuild(ctx context.Context, dockerCli command.Cli, opts *controllerapi.BuildOptions, options buildOptions, printer *progress.Printer) (*client.SolveResponse, error) { func runBasicBuild(ctx context.Context, dockerCli command.Cli, opts *controllerapi.BuildOptions, options buildOptions, printer *progress.Printer) (*client.SolveResponse, error) {
resp, res, err := cbuild.RunBuild(ctx, dockerCli, *opts, os.Stdin, printer, false) resp, res, err := cbuild.RunBuild(ctx, dockerCli, *opts, dockerCli.In(), printer, false)
if res != nil { if res != nil {
res.Done() res.Done()
} }
@@ -346,7 +346,7 @@ func runControllerBuild(ctx context.Context, dockerCli command.Cli, opts *contro
var retErr error var retErr error
var resp *client.SolveResponse var resp *client.SolveResponse
f := ioset.NewSingleForwarder() f := ioset.NewSingleForwarder()
f.SetReader(os.Stdin) f.SetReader(dockerCli.In())
if !options.noBuild { if !options.noBuild {
pr, pw := io.Pipe() pr, pw := io.Pipe()
f.SetWriter(pw, func() io.WriteCloser { f.SetWriter(pw, func() io.WriteCloser {
@@ -487,7 +487,8 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.StringArrayVar(&options.platforms, "platform", platformsDefault, "Set target platform for build") flags.StringArrayVar(&options.platforms, "platform", platformsDefault, "Set target platform for build")
if isExperimental() { if isExperimental() {
flags.StringVar(&options.printFunc, "print", "", "Print result of information request (e.g., outline, targets) [experimental]") flags.StringVar(&options.printFunc, "print", "", "Print result of information request (e.g., outline, targets)")
flags.SetAnnotation("print", "experimentalCLI", nil)
} }
flags.BoolVar(&options.exportPush, "push", false, `Shorthand for "--output=type=registry"`) flags.BoolVar(&options.exportPush, "push", false, `Shorthand for "--output=type=registry"`)
@@ -514,10 +515,14 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--attest=type=provenance"`) flags.StringVar(&options.provenance, "provenance", "", `Shorthand for "--attest=type=provenance"`)
if isExperimental() { if isExperimental() {
flags.StringVar(&invokeFlag, "invoke", "", "Invoke a command after the build [experimental]") flags.StringVar(&invokeFlag, "invoke", "", "Invoke a command after the build")
flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect [experimental]") flags.SetAnnotation("invoke", "experimentalCLI", nil)
flags.BoolVar(&options.Detach, "detach", false, "Detach buildx server (supported only on linux) [experimental]") flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect")
flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server) [experimental]") flags.SetAnnotation("root", "experimentalCLI", nil)
flags.BoolVar(&options.Detach, "detach", false, "Detach buildx server (supported only on linux)")
flags.SetAnnotation("detach", "experimentalCLI", nil)
flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server)")
flags.SetAnnotation("server-config", "experimentalCLI", nil)
} }
// hidden flags // hidden flags
@@ -540,6 +545,7 @@ func buildCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
flags.BoolVar(&ignoreBool, "squash", false, "Squash newly built layers into a single new layer") flags.BoolVar(&ignoreBool, "squash", false, "Squash newly built layers into a single new layer")
flags.MarkHidden("squash") flags.MarkHidden("squash")
flags.SetAnnotation("squash", "flag-warn", []string{"experimental flag squash is removed with BuildKit. You should squash inside build using a multi-stage Dockerfile for efficiency."}) flags.SetAnnotation("squash", "flag-warn", []string{"experimental flag squash is removed with BuildKit. You should squash inside build using a multi-stage Dockerfile for efficiency."})
flags.SetAnnotation("squash", "experimentalCLI", nil)
flags.StringVarP(&ignore, "memory", "m", "", "Memory limit") flags.StringVarP(&ignore, "memory", "m", "", "Memory limit")
flags.MarkHidden("memory") flags.MarkHidden("memory")
@@ -704,6 +710,7 @@ func parseInvokeConfig(invoke string) (cfg invokeConfig, err error) {
} }
csvReader := csv.NewReader(strings.NewReader(invoke)) csvReader := csv.NewReader(strings.NewReader(invoke))
csvReader.LazyQuotes = true
fields, err := csvReader.Read() fields, err := csvReader.Read()
if err != nil { if err != nil {
return cfg, err return cfg, err
@@ -723,11 +730,14 @@ func parseInvokeConfig(invoke string) (cfg invokeConfig, err error) {
value := parts[1] value := parts[1]
switch key { switch key {
case "args": case "args":
cfg.Cmd = append(cfg.Cmd, value) // TODO: support JSON cfg.Cmd = append(cfg.Cmd, maybeJSONArray(value)...)
case "entrypoint": case "entrypoint":
cfg.Entrypoint = append(cfg.Entrypoint, value) // TODO: support JSON cfg.Entrypoint = append(cfg.Entrypoint, maybeJSONArray(value)...)
if cfg.Cmd == nil {
cfg.Cmd = []string{}
}
case "env": case "env":
cfg.Env = append(cfg.Env, value) cfg.Env = append(cfg.Env, maybeJSONArray(value)...)
case "user": case "user":
cfg.User = value cfg.User = value
cfg.NoUser = false cfg.NoUser = false
@@ -746,6 +756,14 @@ func parseInvokeConfig(invoke string) (cfg invokeConfig, err error) {
return cfg, nil return cfg, nil
} }
func maybeJSONArray(v string) []string {
var list []string
if err := json.Unmarshal([]byte(v), &list); err == nil {
return list
}
return []string{v}
}
func listToMap(values []string, defaultEnv bool) map[string]string { func listToMap(values []string, defaultEnv bool) map[string]string {
result := make(map[string]string, len(values)) result := make(map[string]string, len(values))
for _, value := range values { for _, value := range values {

View File

@@ -24,6 +24,9 @@ func debugShellCmd(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{ cmd := &cobra.Command{
Use: "debug-shell", Use: "debug-shell",
Short: "Start a monitor", Short: "Start a monitor",
Annotations: map[string]string{
"experimentalCLI": "",
},
RunE: func(cmd *cobra.Command, args []string) error { RunE: func(cmd *cobra.Command, args []string) error {
printer, err := progress.NewPrinter(context.TODO(), os.Stderr, os.Stderr, progressMode) printer, err := progress.NewPrinter(context.TODO(), os.Stderr, os.Stderr, progressMode)
if err != nil { if err != nil {
@@ -47,7 +50,7 @@ func debugShellCmd(dockerCli command.Cli) *cobra.Command {
err = monitor.RunMonitor(ctx, "", nil, controllerapi.InvokeConfig{ err = monitor.RunMonitor(ctx, "", nil, controllerapi.InvokeConfig{
Tty: true, Tty: true,
}, c, os.Stdin, os.Stdout, os.Stderr, printer) }, c, dockerCli.In(), os.Stdout, os.Stderr, printer)
con.Reset() con.Reset()
return err return err
}, },
@@ -55,9 +58,15 @@ func debugShellCmd(dockerCli command.Cli) *cobra.Command {
flags := cmd.Flags() flags := cmd.Flags()
flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect [experimental]") flags.StringVar(&options.Root, "root", "", "Specify root directory of server to connect")
flags.BoolVar(&options.Detach, "detach", runtime.GOOS == "linux", "Detach buildx server (supported only on linux) [experimental]") flags.SetAnnotation("root", "experimentalCLI", nil)
flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server) [experimental]")
flags.BoolVar(&options.Detach, "detach", runtime.GOOS == "linux", "Detach buildx server (supported only on linux)")
flags.SetAnnotation("detach", "experimentalCLI", nil)
flags.StringVar(&options.ServerConfig, "server-config", "", "Specify buildx server config file (used only when launching new server)")
flags.SetAnnotation("server-config", "experimentalCLI", nil)
flags.StringVar(&progressMode, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`) flags.StringVar(&progressMode, "progress", "auto", `Set type of progress output ("auto", "plain", "tty"). Use plain to show container output`)
return cmd return cmd

View File

@@ -54,6 +54,7 @@ func RunBuild(ctx context.Context, dockerCli command.Cli, in controllerapi.Build
NamedContexts: contexts, NamedContexts: contexts,
}, },
BuildArgs: in.BuildArgs, BuildArgs: in.BuildArgs,
CgroupParent: in.CgroupParent,
ExtraHosts: in.ExtraHosts, ExtraHosts: in.ExtraHosts,
Labels: in.Labels, Labels: in.Labels,
NetworkMode: in.NetworkMode, NetworkMode: in.NetworkMode,

View File

@@ -49,6 +49,16 @@ bin etc lib mnt proc run srv tmp var
dev home media opt root sbin sys usr work dev home media opt root sbin sys usr work
``` ```
Optional long form allows you specifying detailed configurations of the process.
It must be CSV-styled comma-separated key-value pairs.
Supported keys are `args` (can be JSON array format), `entrypoint` (can be JSON array format), `env` (can be JSON array format), `user`, `cwd` and `tty` (bool).
Example:
```
$ docker buildx build --invoke 'entrypoint=["sh"],"args=[""-c"", ""env | grep -e FOO -e AAA""]","env=[""FOO=bar"", ""AAA=bbb""]"' .
```
#### `on-error` #### `on-error`
If you want to start a debug session when a build fails, you can use If you want to start a debug session when a build fails, you can use
@@ -151,4 +161,4 @@ Attached to process "3ug8iqaufiwwnukimhqqt06jz". Press Ctrl-a-c to switch to the
bin etc lib mnt proc run srv tmp var bin etc lib mnt proc run srv tmp var
dev home media opt root sbin sys usr work dev home media opt root sbin sys usr work
/ # / #
``` ```

View File

@@ -9,24 +9,21 @@ Extended build capabilities with BuildKit
### Subcommands ### Subcommands
| Name | Description | | Name | Description |
|:-----------------------------------------------|:-------------------------------------------| |:---------------------------------------|:---------------------------------------|
| [`_INTERNAL_SERVE`](buildx__INTERNAL_SERVE.md) | | | [`bake`](buildx_bake.md) | Build from a file |
| [`bake`](buildx_bake.md) | Build from a file | | [`build`](buildx_build.md) | Start a build |
| [`build`](buildx_build.md) | Start a build | | [`create`](buildx_create.md) | Create a new builder instance |
| [`create`](buildx_create.md) | Create a new builder instance | | [`debug-shell`](buildx_debug-shell.md) | Start a monitor |
| [`debug-shell`](buildx_debug-shell.md) | Start a monitor | | [`du`](buildx_du.md) | Disk usage |
| [`du`](buildx_du.md) | Disk usage | | [`imagetools`](buildx_imagetools.md) | Commands to work on images in registry |
| [`imagetools`](buildx_imagetools.md) | Commands to work on images in registry | | [`inspect`](buildx_inspect.md) | Inspect current builder instance |
| [`inspect`](buildx_inspect.md) | Inspect current builder instance | | [`ls`](buildx_ls.md) | List builder instances |
| [`install`](buildx_install.md) | Install buildx as a 'docker builder' alias | | [`prune`](buildx_prune.md) | Remove build cache |
| [`ls`](buildx_ls.md) | List builder instances | | [`rm`](buildx_rm.md) | Remove a builder instance |
| [`prune`](buildx_prune.md) | Remove build cache | | [`stop`](buildx_stop.md) | Stop builder instance |
| [`rm`](buildx_rm.md) | Remove a builder instance | | [`use`](buildx_use.md) | Set the current builder instance |
| [`stop`](buildx_stop.md) | Stop builder instance | | [`version`](buildx_version.md) | Show buildx version information |
| [`uninstall`](buildx_uninstall.md) | Uninstall the 'docker builder' alias |
| [`use`](buildx_use.md) | Set the current builder instance |
| [`version`](buildx_version.md) | Show buildx version information |
### Options ### Options

View File

@@ -24,10 +24,10 @@ Start a build
| [`--cache-from`](#cache-from) | `stringArray` | | External cache sources (e.g., `user/app:cache`, `type=local,src=path/to/dir`) | | [`--cache-from`](#cache-from) | `stringArray` | | External cache sources (e.g., `user/app:cache`, `type=local,src=path/to/dir`) |
| [`--cache-to`](#cache-to) | `stringArray` | | Cache export destinations (e.g., `user/app:cache`, `type=local,dest=path/to/dir`) | | [`--cache-to`](#cache-to) | `stringArray` | | Cache export destinations (e.g., `user/app:cache`, `type=local,dest=path/to/dir`) |
| [`--cgroup-parent`](https://docs.docker.com/engine/reference/commandline/build/#cgroup-parent) | `string` | | Optional parent cgroup for the container | | [`--cgroup-parent`](https://docs.docker.com/engine/reference/commandline/build/#cgroup-parent) | `string` | | Optional parent cgroup for the container |
| `--detach` | | | Detach buildx server (supported only on linux) [experimental] | | `--detach` | | | Detach buildx server (supported only on linux) |
| [`-f`](https://docs.docker.com/engine/reference/commandline/build/#file), [`--file`](https://docs.docker.com/engine/reference/commandline/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) | | [`-f`](https://docs.docker.com/engine/reference/commandline/build/#file), [`--file`](https://docs.docker.com/engine/reference/commandline/build/#file) | `string` | | Name of the Dockerfile (default: `PATH/Dockerfile`) |
| `--iidfile` | `string` | | Write the image ID to the file | | `--iidfile` | `string` | | Write the image ID to the file |
| `--invoke` | `string` | | Invoke a command after the build [experimental] | | `--invoke` | `string` | | Invoke a command after the build |
| `--label` | `stringArray` | | Set metadata for an image | | `--label` | `stringArray` | | Set metadata for an image |
| [`--load`](#load) | | | Shorthand for `--output=type=docker` | | [`--load`](#load) | | | Shorthand for `--output=type=docker` |
| [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to the file | | [`--metadata-file`](#metadata-file) | `string` | | Write build result metadata to the file |
@@ -36,16 +36,16 @@ Start a build
| `--no-cache-filter` | `stringArray` | | Do not cache specified stages | | `--no-cache-filter` | `stringArray` | | Do not cache specified stages |
| [`-o`](#output), [`--output`](#output) | `stringArray` | | Output destination (format: `type=local,dest=path`) | | [`-o`](#output), [`--output`](#output) | `stringArray` | | Output destination (format: `type=local,dest=path`) |
| [`--platform`](#platform) | `stringArray` | | Set target platform for build | | [`--platform`](#platform) | `stringArray` | | Set target platform for build |
| `--print` | `string` | | Print result of information request (e.g., outline, targets) [experimental] | | `--print` | `string` | | Print result of information request (e.g., outline, targets) |
| [`--progress`](#progress) | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output | | [`--progress`](#progress) | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output |
| [`--provenance`](#provenance) | `string` | | Shorthand for `--attest=type=provenance` | | [`--provenance`](#provenance) | `string` | | Shorthand for `--attest=type=provenance` |
| `--pull` | | | Always attempt to pull all referenced images | | `--pull` | | | Always attempt to pull all referenced images |
| [`--push`](#push) | | | Shorthand for `--output=type=registry` | | [`--push`](#push) | | | Shorthand for `--output=type=registry` |
| `-q`, `--quiet` | | | Suppress the build output and print image ID on success | | `-q`, `--quiet` | | | Suppress the build output and print image ID on success |
| `--root` | `string` | | Specify root directory of server to connect [experimental] | | `--root` | `string` | | Specify root directory of server to connect |
| [`--sbom`](#sbom) | `string` | | Shorthand for `--attest=type=sbom` | | [`--sbom`](#sbom) | `string` | | Shorthand for `--attest=type=sbom` |
| [`--secret`](#secret) | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) | | [`--secret`](#secret) | `stringArray` | | Secret to expose to the build (format: `id=mysecret[,src=/local/secret]`) |
| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) [experimental] | | `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) |
| [`--shm-size`](#shm-size) | `bytes` | `0` | Size of `/dev/shm` | | [`--shm-size`](#shm-size) | `bytes` | `0` | Size of `/dev/shm` |
| [`--ssh`](#ssh) | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) | | [`--ssh`](#ssh) | `stringArray` | | SSH agent socket or keys to expose to the build (format: `default\|<id>[=<socket>\|<key>[,<key>]]`) |
| [`-t`](https://docs.docker.com/engine/reference/commandline/build/#tag), [`--tag`](https://docs.docker.com/engine/reference/commandline/build/#tag) | `stringArray` | | Name and optionally a tag (format: `name:tag`) | | [`-t`](https://docs.docker.com/engine/reference/commandline/build/#tag), [`--tag`](https://docs.docker.com/engine/reference/commandline/build/#tag) | `stringArray` | | Name and optionally a tag (format: `name:tag`) |

View File

@@ -8,10 +8,10 @@ Start a monitor
| Name | Type | Default | Description | | Name | Type | Default | Description |
|:------------------|:---------|:--------|:-----------------------------------------------------------------------------------------| |:------------------|:---------|:--------|:-----------------------------------------------------------------------------------------|
| `--builder` | `string` | | Override the configured builder instance | | `--builder` | `string` | | Override the configured builder instance |
| `--detach` | | | Detach buildx server (supported only on linux) [experimental] | | `--detach` | | | Detach buildx server (supported only on linux) |
| `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output | | `--progress` | `string` | `auto` | Set type of progress output (`auto`, `plain`, `tty`). Use plain to show container output |
| `--root` | `string` | | Specify root directory of server to connect [experimental] | | `--root` | `string` | | Specify root directory of server to connect |
| `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) [experimental] | | `--server-config` | `string` | | Specify buildx server config file (used only when launching new server) |
<!---MARKER_GEN_END--> <!---MARKER_GEN_END-->

View File

@@ -1,11 +0,0 @@
# buildx install
```
docker buildx install
```
<!---MARKER_GEN_START-->
Install buildx as a 'docker builder' alias
<!---MARKER_GEN_END-->

View File

@@ -1,11 +0,0 @@
# buildx uninstall
```
docker buildx uninstall
```
<!---MARKER_GEN_START-->
Uninstall the 'docker builder' alias
<!---MARKER_GEN_END-->

View File

@@ -388,18 +388,11 @@ func (d *Driver) Factory() driver.Factory {
} }
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
var historyAPI bool
c, err := d.Client(ctx)
if err == nil {
historyAPI = driver.HistoryAPISupported(ctx, c)
c.Close()
}
return map[driver.Feature]bool{ return map[driver.Feature]bool{
driver.OCIExporter: true, driver.OCIExporter: true,
driver.DockerExporter: true, driver.DockerExporter: true,
driver.CacheExport: true, driver.CacheExport: true,
driver.MultiPlatform: true, driver.MultiPlatform: true,
driver.HistoryAPI: historyAPI,
} }
} }

View File

@@ -60,7 +60,6 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) {
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
var useContainerdSnapshotter bool var useContainerdSnapshotter bool
var historyAPI bool
c, err := d.Client(ctx) c, err := d.Client(ctx)
if err == nil { if err == nil {
workers, _ := c.ListWorkers(ctx) workers, _ := c.ListWorkers(ctx)
@@ -69,7 +68,6 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
useContainerdSnapshotter = true useContainerdSnapshotter = true
} }
} }
historyAPI = driver.HistoryAPISupported(ctx, c)
c.Close() c.Close()
} }
return map[driver.Feature]bool{ return map[driver.Feature]bool{
@@ -77,7 +75,6 @@ func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
driver.DockerExporter: useContainerdSnapshotter, driver.DockerExporter: useContainerdSnapshotter,
driver.CacheExport: useContainerdSnapshotter, driver.CacheExport: useContainerdSnapshotter,
driver.MultiPlatform: useContainerdSnapshotter, driver.MultiPlatform: useContainerdSnapshotter,
driver.HistoryAPI: historyAPI,
} }
} }

View File

@@ -64,7 +64,7 @@ type Driver interface {
Config() InitConfig Config() InitConfig
} }
func Boot(ctx, clientContext context.Context, d Driver, pw progress.Writer) (*client.Client, error) { func Boot(ctx, clientContext context.Context, d *DriverHandle, pw progress.Writer) (*client.Client, error) {
try := 0 try := 0
for { for {
info, err := d.Info(ctx) info, err := d.Info(ctx)
@@ -92,7 +92,7 @@ func Boot(ctx, clientContext context.Context, d Driver, pw progress.Writer) (*cl
} }
} }
func HistoryAPISupported(ctx context.Context, c *client.Client) bool { func historyAPISupported(ctx context.Context, c *client.Client) bool {
cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{ cl, err := c.ControlClient().ListenBuildHistory(ctx, &controlapi.BuildHistoryRequest{
ActiveOnly: true, ActiveOnly: true,
Ref: "buildx-test-history-api-feature", // dummy ref to check if the server supports the API Ref: "buildx-test-history-api-feature", // dummy ref to check if the server supports the API

View File

@@ -7,5 +7,3 @@ const DockerExporter Feature = "Docker exporter"
const CacheExport Feature = "Cache export" const CacheExport Feature = "Cache export"
const MultiPlatform Feature = "Multiple platforms" const MultiPlatform Feature = "Multiple platforms"
const HistoryAPI Feature = "History API"

View File

@@ -229,17 +229,10 @@ func (d *Driver) Factory() driver.Factory {
} }
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
var historyAPI bool
c, err := d.Client(ctx)
if err == nil {
historyAPI = driver.HistoryAPISupported(ctx, c)
c.Close()
}
return map[driver.Feature]bool{ return map[driver.Feature]bool{
driver.OCIExporter: true, driver.OCIExporter: true,
driver.DockerExporter: d.DockerAPI != nil, driver.DockerExporter: d.DockerAPI != nil,
driver.CacheExport: true, driver.CacheExport: true,
driver.MultiPlatform: true, // Untested (needs multiple Driver instances) driver.MultiPlatform: true, // Untested (needs multiple Driver instances)
driver.HistoryAPI: historyAPI,
} }
} }

View File

@@ -2,17 +2,17 @@ package driver
import ( import (
"context" "context"
"net"
"os" "os"
"sort" "sort"
"strings" "strings"
"sync" "sync"
"k8s.io/client-go/rest"
dockerclient "github.com/docker/docker/client" dockerclient "github.com/docker/docker/client"
"github.com/moby/buildkit/client" "github.com/moby/buildkit/client"
specs "github.com/opencontainers/image-spec/specs-go/v1" specs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors" "github.com/pkg/errors"
"k8s.io/client-go/rest"
) )
type Factory interface { type Factory interface {
@@ -104,7 +104,7 @@ func GetFactory(name string, instanceRequired bool) (Factory, error) {
return nil, errors.Errorf("failed to find driver %q", name) return nil, errors.Errorf("failed to find driver %q", name)
} }
func GetDriver(ctx context.Context, name string, f Factory, endpointAddr string, api dockerclient.APIClient, auth Auth, kcc KubeClientConfig, flags []string, files map[string][]byte, do map[string]string, platforms []specs.Platform, contextPathHash string) (Driver, error) { func GetDriver(ctx context.Context, name string, f Factory, endpointAddr string, api dockerclient.APIClient, auth Auth, kcc KubeClientConfig, flags []string, files map[string][]byte, do map[string]string, platforms []specs.Platform, contextPathHash string) (*DriverHandle, error) {
ic := InitConfig{ ic := InitConfig{
EndpointAddr: endpointAddr, EndpointAddr: endpointAddr,
DockerAPI: api, DockerAPI: api,
@@ -128,7 +128,7 @@ func GetDriver(ctx context.Context, name string, f Factory, endpointAddr string,
if err != nil { if err != nil {
return nil, err return nil, err
} }
return &cachedDriver{Driver: d}, nil return &DriverHandle{Driver: d}, nil
} }
func GetFactories(instanceRequired bool) []Factory { func GetFactories(instanceRequired bool) []Factory {
@@ -145,25 +145,72 @@ func GetFactories(instanceRequired bool) []Factory {
return ds return ds
} }
type cachedDriver struct { type DriverHandle struct {
Driver Driver
client *client.Client client *client.Client
err error err error
once sync.Once once sync.Once
featuresOnce sync.Once featuresOnce sync.Once
features map[Feature]bool features map[Feature]bool
historyAPISupportedOnce sync.Once
historyAPISupported bool
hostGatewayIPOnce sync.Once
hostGatewayIP net.IP
hostGatewayIPErr error
} }
func (d *cachedDriver) Client(ctx context.Context) (*client.Client, error) { func (d *DriverHandle) Client(ctx context.Context) (*client.Client, error) {
d.once.Do(func() { d.once.Do(func() {
d.client, d.err = d.Driver.Client(ctx) d.client, d.err = d.Driver.Client(ctx)
}) })
return d.client, d.err return d.client, d.err
} }
func (d *cachedDriver) Features(ctx context.Context) map[Feature]bool { func (d *DriverHandle) Features(ctx context.Context) map[Feature]bool {
d.featuresOnce.Do(func() { d.featuresOnce.Do(func() {
d.features = d.Driver.Features(ctx) d.features = d.Driver.Features(ctx)
}) })
return d.features return d.features
} }
func (d *DriverHandle) HistoryAPISupported(ctx context.Context) bool {
d.historyAPISupportedOnce.Do(func() {
if c, err := d.Client(ctx); err == nil {
d.historyAPISupported = historyAPISupported(ctx, c)
}
})
return d.historyAPISupported
}
func (d *DriverHandle) HostGatewayIP(ctx context.Context) (net.IP, error) {
d.hostGatewayIPOnce.Do(func() {
if !d.Driver.IsMobyDriver() {
d.hostGatewayIPErr = errors.New("host-gateway is only supported with the docker driver")
return
}
c, err := d.Client(ctx)
if err != nil {
d.hostGatewayIPErr = err
return
}
workers, err := c.ListWorkers(ctx)
if err != nil {
d.hostGatewayIPErr = errors.Wrap(err, "listing workers")
return
}
for _, w := range workers {
// should match github.com/docker/docker/builder/builder-next/worker/label.HostGatewayIP const
if v, ok := w.Labels["org.mobyproject.buildkit.worker.moby.host-gateway-ip"]; ok && v != "" {
ip := net.ParseIP(v)
if ip == nil {
d.hostGatewayIPErr = errors.Errorf("failed to parse host-gateway IP: %s", v)
return
}
d.hostGatewayIP = ip
return
}
}
d.hostGatewayIPErr = errors.New("host-gateway IP not found")
})
return d.hostGatewayIP, d.hostGatewayIPErr
}

View File

@@ -88,18 +88,11 @@ func (d *Driver) Client(ctx context.Context) (*client.Client, error) {
} }
func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool { func (d *Driver) Features(ctx context.Context) map[driver.Feature]bool {
var historyAPI bool
c, err := d.Client(ctx)
if err == nil {
historyAPI = driver.HistoryAPISupported(ctx, c)
c.Close()
}
return map[driver.Feature]bool{ return map[driver.Feature]bool{
driver.OCIExporter: true, driver.OCIExporter: true,
driver.DockerExporter: true, driver.DockerExporter: true,
driver.CacheExport: true, driver.CacheExport: true,
driver.MultiPlatform: true, driver.MultiPlatform: true,
driver.HistoryAPI: historyAPI,
} }
} }

12
go.mod
View File

@@ -7,13 +7,13 @@ require (
github.com/aws/aws-sdk-go-v2/config v1.18.16 github.com/aws/aws-sdk-go-v2/config v1.18.16
github.com/compose-spec/compose-go v1.14.0 github.com/compose-spec/compose-go v1.14.0
github.com/containerd/console v1.0.3 github.com/containerd/console v1.0.3
github.com/containerd/containerd v1.7.1 github.com/containerd/containerd v1.7.2
github.com/containerd/continuity v0.4.1 github.com/containerd/continuity v0.4.1
github.com/containerd/typeurl/v2 v2.1.1 github.com/containerd/typeurl/v2 v2.1.1
github.com/docker/cli v24.0.1+incompatible github.com/docker/cli v24.0.2+incompatible
github.com/docker/cli-docs-tool v0.5.1 github.com/docker/cli-docs-tool v0.6.0
github.com/docker/distribution v2.8.2+incompatible github.com/docker/distribution v2.8.2+incompatible
github.com/docker/docker v24.0.1+incompatible github.com/docker/docker v24.0.2+incompatible
github.com/docker/go-units v0.5.0 github.com/docker/go-units v0.5.0
github.com/gofrs/flock v0.8.1 github.com/gofrs/flock v0.8.1
github.com/gogo/protobuf v1.3.2 github.com/gogo/protobuf v1.3.2
@@ -22,7 +22,7 @@ require (
github.com/google/uuid v1.3.0 github.com/google/uuid v1.3.0
github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840 github.com/hashicorp/go-cty-funcs v0.0.0-20200930094925-2721b1e36840
github.com/hashicorp/hcl/v2 v2.8.2 github.com/hashicorp/hcl/v2 v2.8.2
github.com/moby/buildkit v0.11.0-rc3.0.20230530080511-c36941f4a10e github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a
github.com/moby/sys/mountinfo v0.6.2 github.com/moby/sys/mountinfo v0.6.2
github.com/moby/sys/signal v0.7.0 github.com/moby/sys/signal v0.7.0
github.com/morikuni/aec v1.0.0 github.com/morikuni/aec v1.0.0
@@ -140,7 +140,7 @@ require (
github.com/theupdateframework/notary v0.6.1 // indirect github.com/theupdateframework/notary v0.6.1 // indirect
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 // indirect github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 // indirect
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f // indirect github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 // indirect
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f // indirect
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
github.com/xeipuuv/gojsonschema v1.2.0 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect

27
go.sum
View File

@@ -127,8 +127,8 @@ github.com/compose-spec/compose-go v1.14.0/go.mod h1:m0o4G6MQDHjjz9rY7No9FpnNi+9
github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM=
github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw=
github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U=
github.com/containerd/containerd v1.7.1 h1:k8DbDkSOwt5rgxQ3uCI4WMKIJxIndSCBUaGm5oRn+Go= github.com/containerd/containerd v1.7.2 h1:UF2gdONnxO8I6byZXDi5sXWiWvlW3D/sci7dTQimEJo=
github.com/containerd/containerd v1.7.1/go.mod h1:gA+nJUADRBm98QS5j5RPROnt0POQSMK+r7P7EGMC/Qc= github.com/containerd/containerd v1.7.2/go.mod h1:afcz74+K10M/+cjGHIVQrCt3RAQhUSCAjJ9iMYhhkuI=
github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU= github.com/containerd/continuity v0.4.1 h1:wQnVrjIyQ8vhU2sgOiL5T07jo+ouqc2bnKsv5/EqGhU=
github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/continuity v0.4.1/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ=
github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY= github.com/containerd/fifo v1.1.0 h1:4I2mbh5stb1u6ycIABlBw9zgtlK8viPI9QkQNRQEEmY=
@@ -149,14 +149,14 @@ github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa h1:L9Ay/slwQ4ERSPaurC+TVkZrM0K98GNrEEo1En3e8as= github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa h1:L9Ay/slwQ4ERSPaurC+TVkZrM0K98GNrEEo1En3e8as=
github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI=
github.com/docker/cli v24.0.1+incompatible h1:uVl5Xv/39kZJpDo9VaktTOYBc702sdYYF33FqwUG/dM= github.com/docker/cli v24.0.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM=
github.com/docker/cli v24.0.1+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.5.1 h1:jIk/cCZurZERhALPVKhqlNxTQGxn2kcI+56gE57PQXg= github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA=
github.com/docker/cli-docs-tool v0.5.1/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= github.com/docker/cli-docs-tool v0.6.0/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o=
github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8= github.com/docker/distribution v2.8.2+incompatible h1:T3de5rq0dB1j30rp0sA2rER+m322EBzniBPB6ZIzuh8=
github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/distribution v2.8.2+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v24.0.1+incompatible h1:NxN81beIxDlUaVt46iUQrYHD9/W3u9EGl52r86O/IGw= github.com/docker/docker v24.0.2+incompatible h1:eATx+oLz9WdNVkQrr0qjQ8HvRJ4bOOxfzEo8R+dA3cg=
github.com/docker/docker v24.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v24.0.2+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A= github.com/docker/docker-credential-helpers v0.7.0 h1:xtCHsjxogADNZcdv1pKUHXryefjlVRqWqIhk/uXJp0A=
github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0= github.com/docker/docker-credential-helpers v0.7.0/go.mod h1:rETQfLdHNT3foU5kuNkFR1R1V12OJRRO5lzt2D1b5X0=
github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0=
@@ -371,8 +371,8 @@ github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzC
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo= github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/moby/buildkit v0.11.0-rc3.0.20230530080511-c36941f4a10e h1:d5nOEUewXcVebVTyUVeQHXX8+Ofb/+TSlqZSn9xIg3k= github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a h1:1k3bAXwxC2N1FncWijq/43sLj2OVIZ11FT0APIXWhMg=
github.com/moby/buildkit v0.11.0-rc3.0.20230530080511-c36941f4a10e/go.mod h1:nWISTd0U2LNfp6z0W5T0NO73xO5rrdRiTTQkSF6uIjc= github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a/go.mod h1:4sM7BBBqXOQ+vV6LrVAOAMhZI9cVNYV5RhZCl906a64=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc=
github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo= github.com/moby/patternmatcher v0.5.0 h1:YCZgJOeULcxLw1Q+sVR636pmS7sPEn1Qo2iAN6M7DBo=
@@ -411,7 +411,6 @@ github.com/opencontainers/runc v1.1.7/go.mod h1:CbUumNnWCuTGFukNXahoo/RFBZvDAgRh
github.com/opencontainers/runtime-spec v1.1.0-rc.2 h1:ucBtEms2tamYYW/SvGpvq9yUN0NEVL6oyLEwDcTSrk8= github.com/opencontainers/runtime-spec v1.1.0-rc.2 h1:ucBtEms2tamYYW/SvGpvq9yUN0NEVL6oyLEwDcTSrk8=
github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU= github.com/opencontainers/selinux v1.11.0 h1:+5Zbo97w3Lbmb3PeqQtpmTkMwsW5nRI3YaLpt7tQ7oU=
github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o=
github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o=
github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8=
github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg=
@@ -460,7 +459,7 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spdx/tools-golang v0.5.0 h1:/fqihV2Jna7fmow65dHpgKNsilgLK7ICpd2tkCnPEyY= github.com/spdx/tools-golang v0.5.1 h1:fJg3SVOGG+eIva9ZUBm/hvyA7PIPVFjRxUKe6fdAgwE=
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw= github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w= github.com/spf13/cast v1.5.0 h1:rj3WzYc11XZaIZMPKmwP96zkFEnnAmV8s6XbB2aY32w=
github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I= github.com/spf13/cobra v1.7.0 h1:hyqWnYt1ZQShIddO5kBpj3vu05/++x6tJ6dg8EC572I=
@@ -489,8 +488,8 @@ github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576 h1:fZXPQDVh5fm2x
github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576/go.mod h1:q1CxMSzcAbjUkVGHoZeQUcCaALnaE4XdWk+zJcgMYFw= github.com/tonistiigi/fsutil v0.0.0-20230407161946-9e7a6df48576/go.mod h1:q1CxMSzcAbjUkVGHoZeQUcCaALnaE4XdWk+zJcgMYFw=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0=
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk=
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f h1:DLpt6B5oaaS8jyXHa9VA4rrZloBVPVXeCtrOsrFauxc= github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531 h1:Y/M5lygoNPKwVNLMPXgVfsRT40CSFKXCxuU8LoHySjs=
github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc=
github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME= github.com/vbatts/tar-split v0.11.2 h1:Via6XqJr0hceW4wff3QRzD5gAk/tatMw/4ZA7cTlIME=
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk= github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4= github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=

View File

@@ -282,6 +282,7 @@ func (m *monitor) startInvoke(ctx context.Context, pid string, cfg controllerapi
} }
if len(cfg.Entrypoint) == 0 && len(cfg.Cmd) == 0 { if len(cfg.Entrypoint) == 0 && len(cfg.Cmd) == 0 {
cfg.Entrypoint = []string{"sh"} // launch shell by default cfg.Entrypoint = []string{"sh"} // launch shell by default
cfg.Cmd = []string{}
} }
go func() { go func() {
// Start a new invoke // Start a new invoke

View File

@@ -235,3 +235,26 @@ func TestNodeManagement(t *testing.T) {
require.NotNil(t, ng) require.NotNil(t, ng)
require.Equal(t, "mybuild", ng.Name) require.Equal(t, "mybuild", ng.Name)
} }
func TestNodeInvalidName(t *testing.T) {
t.Parallel()
tmpdir := t.TempDir()
s, err := New(tmpdir)
require.NoError(t, err)
txn, release, err := s.Txn()
require.NoError(t, err)
defer release()
_, err = txn.NodeGroupByName("123builder")
require.Error(t, err)
require.True(t, IsErrInvalidName(err))
err = txn.Save(&NodeGroup{
Name: "123builder",
Driver: "mydriver",
})
require.Error(t, err)
require.True(t, IsErrInvalidName(err))
}

View File

@@ -74,7 +74,7 @@ func GetCurrentInstance(txn *store.Txn, dockerCli command.Cli) (*store.NodeGroup
func GetNodeGroup(txn *store.Txn, dockerCli command.Cli, name string) (*store.NodeGroup, error) { func GetNodeGroup(txn *store.Txn, dockerCli command.Cli, name string) (*store.NodeGroup, error) {
ng, err := txn.NodeGroupByName(name) ng, err := txn.NodeGroupByName(name)
if err != nil { if err != nil {
if !os.IsNotExist(errors.Cause(err)) { if !os.IsNotExist(errors.Cause(err)) && !store.IsErrInvalidName(err) {
return nil, err return nil, err
} }
} }

View File

@@ -11,9 +11,28 @@ import (
var namePattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9\.\-_]*$`) var namePattern = regexp.MustCompile(`^[a-zA-Z][a-zA-Z0-9\.\-_]*$`)
type errInvalidName struct {
error
}
func (e *errInvalidName) Error() string {
return e.error.Error()
}
func (e *errInvalidName) Unwrap() error {
return e.error
}
func IsErrInvalidName(err error) bool {
_, ok := err.(*errInvalidName)
return ok
}
func ValidateName(s string) (string, error) { func ValidateName(s string) (string, error) {
if !namePattern.MatchString(s) { if !namePattern.MatchString(s) {
return "", errors.Errorf("invalid name %s, name needs to start with a letter and may not contain symbols, except ._-", s) return "", &errInvalidName{
errors.Errorf("invalid name %s, name needs to start with a letter and may not contain symbols, except ._-", s),
}
} }
return strings.ToLower(s), nil return strings.ToLower(s), nil
} }

View File

@@ -3,10 +3,11 @@ package tests
import ( import (
"bytes" "bytes"
"encoding/json" "encoding/json"
"errors"
"fmt" "fmt"
"os" "os"
"path"
"path/filepath" "path/filepath"
"regexp"
"strings" "strings"
"testing" "testing"
@@ -16,6 +17,7 @@ import (
"github.com/moby/buildkit/util/testutil" "github.com/moby/buildkit/util/testutil"
"github.com/moby/buildkit/util/testutil/integration" "github.com/moby/buildkit/util/testutil/integration"
"github.com/opencontainers/go-digest" "github.com/opencontainers/go-digest"
"github.com/pkg/errors"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
@@ -32,6 +34,7 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
testBuildLocalExport, testBuildLocalExport,
testBuildRegistryExport, testBuildRegistryExport,
testBuildTarExport, testBuildTarExport,
testBuildDetailsLink,
} }
func testBuild(t *testing.T, sb integration.Sandbox) { func testBuild(t *testing.T, sb integration.Sandbox) {
@@ -139,6 +142,48 @@ func testImageIDOutput(t *testing.T, sb integration.Sandbox) {
require.Equal(t, dgst, digest.Digest(md.ConfigDigest)) require.Equal(t, dgst, digest.Digest(md.ConfigDigest))
} }
func testBuildDetailsLink(t *testing.T, sb integration.Sandbox) {
buildDetailsPattern := regexp.MustCompile(`(?m)^View build details: docker-desktop://dashboard/build/[^/]+/[^/]+/[^/]+\n$`)
// build simple dockerfile
dockerfile := []byte(`FROM busybox:latest
RUN echo foo > /bar`)
dir := tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
cmd := buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out))
require.False(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("build details link not expected in output, got %q", out))
// create desktop-build .lastaccess file
home, err := os.UserHomeDir() // TODO: sandbox should create a temp home dir and expose it through its interface
require.NoError(t, err)
dbDir := path.Join(home, ".docker", "desktop-build")
require.NoError(t, os.MkdirAll(dbDir, 0755))
dblaFile, err := os.Create(path.Join(dbDir, ".lastaccess"))
require.NoError(t, err)
defer func() {
dblaFile.Close()
if err := os.Remove(dblaFile.Name()); err != nil {
t.Fatal(err)
}
}()
// build again
cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err = cmd.CombinedOutput()
require.NoError(t, err, string(out))
require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out))
// build erroneous dockerfile
dockerfile = []byte(`FROM busybox:latest
RUN exit 1`)
dir = tmpdir(t, fstest.CreateFile("Dockerfile", dockerfile, 0600))
cmd = buildxCmd(sb, withArgs("build", "--output=type=cacheonly", dir))
out, err = cmd.CombinedOutput()
require.Error(t, err, string(out))
require.True(t, buildDetailsPattern.MatchString(string(out)), fmt.Sprintf("expected build details link in output, got %q", out))
}
func createTestProject(t *testing.T) string { func createTestProject(t *testing.T) string {
dockerfile := []byte(` dockerfile := []byte(`
FROM busybox:latest AS base FROM busybox:latest AS base

View File

@@ -19,7 +19,7 @@ func Disable(cmd *cobra.Command, args []string, toComplete string) ([]string, co
func BakeTargets(files []string) ValidArgsFn { func BakeTargets(files []string) ValidArgsFn {
return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { return func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
f, err := bake.ReadLocalFiles(files) f, err := bake.ReadLocalFiles(files, nil)
if err != nil { if err != nil {
return nil, cobra.ShellCompDirectiveError return nil, cobra.ShellCompDirectiveError
} }

View File

@@ -81,6 +81,6 @@ func (e *ErrorWithBuildRef) Print(w io.Writer) error {
if _, err := console.ConsoleFromFile(os.Stderr); err == nil { if _, err := console.ConsoleFromFile(os.Stderr); err == nil {
term = true term = true
} }
fmt.Fprintf(w, "\n%s", BuildDetailsOutput(map[string]string{"default": e.Ref}, term)) fmt.Fprintf(w, "\n%s\n", BuildDetailsOutput(map[string]string{"default": e.Ref}, term))
return nil return nil
} }

View File

@@ -13,6 +13,9 @@ import (
// Client represents an active docker object. // Client represents an active docker object.
type Client struct { type Client struct {
cli command.Cli cli command.Cli
featuresOnce sync.Once
featuresCache map[Feature]bool
} }
// NewClient initializes a new docker client. // NewClient initializes a new docker client.
@@ -64,6 +67,13 @@ func (c *Client) LoadImage(ctx context.Context, name string, status progress.Wri
} }
func (c *Client) Features(ctx context.Context, name string) map[Feature]bool { func (c *Client) Features(ctx context.Context, name string) map[Feature]bool {
c.featuresOnce.Do(func() {
c.featuresCache = c.features(ctx, name)
})
return c.featuresCache
}
func (c *Client) features(ctx context.Context, name string) map[Feature]bool {
features := make(map[Feature]bool) features := make(map[Feature]bool)
if dapi, err := c.API(name); err == nil { if dapi, err := c.API(name); err == nil {
if info, err := dapi.Info(ctx); err == nil { if info, err := dapi.Info(ctx); err == nil {

View File

@@ -98,25 +98,30 @@ type ResolverOptions struct {
Tracker StatusTracker Tracker StatusTracker
// Authorizer is used to authorize registry requests // Authorizer is used to authorize registry requests
// Deprecated: use Hosts //
// Deprecated: use Hosts.
Authorizer Authorizer Authorizer Authorizer
// Credentials provides username and secret given a host. // Credentials provides username and secret given a host.
// If username is empty but a secret is given, that secret // If username is empty but a secret is given, that secret
// is interpreted as a long lived token. // is interpreted as a long lived token.
// Deprecated: use Hosts //
// Deprecated: use Hosts.
Credentials func(string) (string, string, error) Credentials func(string) (string, string, error)
// Host provides the hostname given a namespace. // Host provides the hostname given a namespace.
// Deprecated: use Hosts //
// Deprecated: use Hosts.
Host func(string) (string, error) Host func(string) (string, error)
// PlainHTTP specifies to use plain http and not https // PlainHTTP specifies to use plain http and not https
// Deprecated: use Hosts //
// Deprecated: use Hosts.
PlainHTTP bool PlainHTTP bool
// Client is the http client to used when making registry requests // Client is the http client to used when making registry requests
// Deprecated: use Hosts //
// Deprecated: use Hosts.
Client *http.Client Client *http.Client
} }

View File

@@ -23,7 +23,7 @@ var (
Package = "github.com/containerd/containerd" Package = "github.com/containerd/containerd"
// Version holds the complete version number. Filled in at linking time. // Version holds the complete version number. Filled in at linking time.
Version = "1.7.1+unknown" Version = "1.7.2+unknown"
// Revision is filled with the VCS (e.g. git) revision being used to build // Revision is filled with the VCS (e.g. git) revision being used to build
// the program at linking time. // the program at linking time.

View File

@@ -53,6 +53,12 @@ func (c *Client) GenMarkdownTree(cmd *cobra.Command) error {
return nil return nil
} }
// Skip hidden command
if cmd.Hidden {
log.Printf("INFO: Skipping Markdown for %q (hidden command)", cmd.CommandPath())
return nil
}
log.Printf("INFO: Generating Markdown for %q", cmd.CommandPath()) log.Printf("INFO: Generating Markdown for %q", cmd.CommandPath())
mdFile := mdFilename(cmd) mdFile := mdFilename(cmd)
sourcePath := filepath.Join(c.source, mdFile) sourcePath := filepath.Join(c.source, mdFile)
@@ -208,6 +214,9 @@ func mdCmdOutput(cmd *cobra.Command, old string) (string, error) {
b.WriteString("### Subcommands\n\n") b.WriteString("### Subcommands\n\n")
table := newMdTable("Name", "Description") table := newMdTable("Name", "Description")
for _, c := range cmd.Commands() { for _, c := range cmd.Commands() {
if c.Hidden {
continue
}
table.AddRow(fmt.Sprintf("[`%s`](%s)", c.Name(), mdFilename(c)), c.Short) table.AddRow(fmt.Sprintf("[`%s`](%s)", c.Name(), mdFilename(c)), c.Short)
} }
b.WriteString(table.String() + "\n") b.WriteString(table.String() + "\n")

View File

@@ -62,6 +62,7 @@ type cmdDoc struct {
InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"` InheritedOptions []cmdOption `yaml:"inherited_options,omitempty"`
Example string `yaml:"examples,omitempty"` Example string `yaml:"examples,omitempty"`
Deprecated bool Deprecated bool
Hidden bool
MinAPIVersion string `yaml:"min_api_version,omitempty"` MinAPIVersion string `yaml:"min_api_version,omitempty"`
Experimental bool Experimental bool
ExperimentalCLI bool ExperimentalCLI bool
@@ -155,6 +156,7 @@ func (c *Client) genYamlCustom(cmd *cobra.Command, w io.Writer) error {
Long: forceMultiLine(cmd.Long, longMaxWidth), Long: forceMultiLine(cmd.Long, longMaxWidth),
Example: cmd.Example, Example: cmd.Example,
Deprecated: len(cmd.Deprecated) > 0, Deprecated: len(cmd.Deprecated) > 0,
Hidden: cmd.Hidden,
} }
if len(cliDoc.Long) == 0 { if len(cliDoc.Long) == 0 {

View File

@@ -0,0 +1,75 @@
package exptypes
import commonexptypes "github.com/moby/buildkit/exporter/exptypes"
type ImageExporterOptKey string
// Options keys supported by the image exporter output.
var (
// Name of the image.
// Value: string
OptKeyName ImageExporterOptKey = "name"
// Push after creating image.
// Value: bool <true|false>
OptKeyPush ImageExporterOptKey = "push"
// Push unnamed image.
// Value: bool <true|false>
OptKeyPushByDigest ImageExporterOptKey = "push-by-digest"
// Allow pushing to insecure HTTP registry.
// Value: bool <true|false>
OptKeyInsecure ImageExporterOptKey = "registry.insecure"
// Unpack image after it's created (containerd).
// Value: bool <true|false>
OptKeyUnpack ImageExporterOptKey = "unpack"
// Fallback image name prefix if image name isn't provided.
// If used, image will be named as <value>@<digest>
// Value: string
OptKeyDanglingPrefix ImageExporterOptKey = "dangling-name-prefix"
// Creates additional image name with format <name>@<digest>
// Value: bool <true|false>
OptKeyNameCanonical ImageExporterOptKey = "name-canonical"
// Store the resulting image along with all of the content it references.
// Ignored if the worker doesn't have image store (e.g. OCI worker).
// Value: bool <true|false>
OptKeyStore ImageExporterOptKey = "store"
// Use OCI mediatypes instead of Docker in JSON configs.
// Value: bool <true|false>
OptKeyOCITypes ImageExporterOptKey = "oci-mediatypes"
// Force attestation to be attached.
// Value: bool <true|false>
OptKeyForceInlineAttestations ImageExporterOptKey = "attestation-inline"
// Mark layers as non-distributable if they are found to use a
// non-distributable media type. When this option is not set, the exporter
// will change the media type of the layer to a distributable one.
// Value: bool <true|false>
OptKeyPreferNondistLayers ImageExporterOptKey = "prefer-nondist-layers"
// Clamp produced timestamps. For more information see the
// SOURCE_DATE_EPOCH specification.
// Value: int (number of seconds since Unix epoch)
OptKeySourceDateEpoch ImageExporterOptKey = ImageExporterOptKey(commonexptypes.OptKeySourceDateEpoch)
// Compression type for newly created and cached layers.
// estargz should be used with OptKeyOCITypes set to true.
// Value: string <uncompressed|gzip|estargz|zstd>
OptKeyLayerCompression ImageExporterOptKey = "compression"
// Force compression on all (including existing) layers.
// Value: bool <true|false>
OptKeyForceCompression ImageExporterOptKey = "force-compression"
// Compression level
// Value: int (0-9) for gzip and estargz
// Value: int (0-22) for zstd
OptKeyCompressionLevel ImageExporterOptKey = "compression-level"
)

View File

@@ -12,7 +12,6 @@ const (
ExporterImageDescriptorKey = "containerimage.descriptor" ExporterImageDescriptorKey = "containerimage.descriptor"
ExporterInlineCache = "containerimage.inlinecache" ExporterInlineCache = "containerimage.inlinecache"
ExporterPlatformsKey = "refs.platforms" ExporterPlatformsKey = "refs.platforms"
ExporterEpochKey = "source.date.epoch"
) )
// KnownRefMetadataKeys are the subset of exporter keys that can be suffixed by // KnownRefMetadataKeys are the subset of exporter keys that can be suffixed by

View File

@@ -0,0 +1,15 @@
package exptypes
const (
ExporterEpochKey = "source.date.epoch"
)
type ExporterOptKey string
// Options keys supported by all exporters.
var (
// Clamp produced timestamps. For more information see the
// SOURCE_DATE_EPOCH specification.
// Value: int (number of seconds since Unix epoch)
OptKeySourceDateEpoch ExporterOptKey = "source-date-epoch"
)

View File

@@ -29,6 +29,8 @@ import (
) )
const defaultExpiration = 60 const defaultExpiration = 60
const dockerHubConfigfileKey = "https://index.docker.io/v1/"
const dockerHubRegistryHost = "registry-1.docker.io"
func NewDockerAuthProvider(cfg *configfile.ConfigFile) session.Attachable { func NewDockerAuthProvider(cfg *configfile.ConfigFile) session.Attachable {
return &authProvider{ return &authProvider{
@@ -183,10 +185,12 @@ func (ap *authProvider) VerifyTokenAuthority(ctx context.Context, req *auth.Veri
func (ap *authProvider) getAuthConfig(host string) (*types.AuthConfig, error) { func (ap *authProvider) getAuthConfig(host string) (*types.AuthConfig, error) {
ap.mu.Lock() ap.mu.Lock()
defer ap.mu.Unlock() defer ap.mu.Unlock()
if host == dockerHubRegistryHost {
host = dockerHubConfigfileKey
}
if _, exists := ap.authConfigCache[host]; !exists { if _, exists := ap.authConfigCache[host]; !exists {
if host == "registry-1.docker.io" {
host = "https://index.docker.io/v1/"
}
ac, err := ap.config.GetAuthConfig(host) ac, err := ap.config.GetAuthConfig(host)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -143,10 +143,13 @@ func (p *textMux) printVtx(t *trace, dgst digest.Digest) {
} }
for i, l := range v.logs { for i, l := range v.logs {
if i == 0 { if i == 0 && v.logsOffset != 0 { // index has already been printed
l = l[v.logsOffset:] l = l[v.logsOffset:]
fmt.Fprintf(p.w, "%s", l)
} else {
fmt.Fprintf(p.w, "#%d %s", v.index, []byte(l))
} }
fmt.Fprintf(p.w, "#%d %s", v.index, []byte(l))
if i != len(v.logs)-1 || !v.logsPartial { if i != len(v.logs)-1 || !v.logsPartial {
fmt.Fprintln(p.w, "") fmt.Fprintln(p.w, "")
} }

View File

@@ -1,5 +1,13 @@
package system package system
import (
"path"
"path/filepath"
"strings"
"github.com/pkg/errors"
)
// DefaultPathEnvUnix is unix style list of directories to search for // DefaultPathEnvUnix is unix style list of directories to search for
// executables. Each directory is separated from the next by a colon // executables. Each directory is separated from the next by a colon
// ':' character . // ':' character .
@@ -16,3 +24,202 @@ func DefaultPathEnv(os string) string {
} }
return DefaultPathEnvUnix return DefaultPathEnvUnix
} }
// NormalizePath cleans the path based on the operating system the path is meant for.
// It takes into account a potential parent path, and will join the path to the parent
// if the path is relative. Additionally, it will apply the folliwing rules:
// - always return an absolute path
// - always strip drive letters for Windows paths
// - optionally keep the trailing slashes on paths
// - paths are returned using forward slashes
func NormalizePath(parent, newPath, inputOS string, keepSlash bool) (string, error) {
if inputOS == "" {
inputOS = "linux"
}
newPath = toSlash(newPath, inputOS)
parent = toSlash(parent, inputOS)
origPath := newPath
if parent == "" {
parent = "/"
}
var err error
parent, err = CheckSystemDriveAndRemoveDriveLetter(parent, inputOS)
if err != nil {
return "", errors.Wrap(err, "removing drive letter")
}
if !IsAbs(parent, inputOS) {
parent = path.Join("/", parent)
}
if newPath == "" {
// New workdir is empty. Use the "current" workdir. It should already
// be an absolute path.
newPath = parent
}
newPath, err = CheckSystemDriveAndRemoveDriveLetter(newPath, inputOS)
if err != nil {
return "", errors.Wrap(err, "removing drive letter")
}
if !IsAbs(newPath, inputOS) {
// The new WD is relative. Join it to the previous WD.
newPath = path.Join(parent, newPath)
}
if keepSlash {
if strings.HasSuffix(origPath, "/") && !strings.HasSuffix(newPath, "/") {
newPath += "/"
} else if strings.HasSuffix(origPath, "/.") {
if newPath != "/" {
newPath += "/"
}
newPath += "."
}
}
return toSlash(newPath, inputOS), nil
}
func toSlash(inputPath, inputOS string) string {
separator := "/"
if inputOS == "windows" {
separator = "\\"
}
return strings.Replace(inputPath, separator, "/", -1)
}
func fromSlash(inputPath, inputOS string) string {
separator := "/"
if inputOS == "windows" {
separator = "\\"
}
return strings.Replace(inputPath, "/", separator, -1)
}
// NormalizeWorkdir will return a normalized version of the new workdir, given
// the currently configured workdir and the desired new workdir. When setting a
// new relative workdir, it will be joined to the previous workdir or default to
// the root folder.
// On Windows we remove the drive letter and convert the path delimiter to "\".
// Paths that begin with os.PathSeparator are considered absolute even on Windows.
func NormalizeWorkdir(current, wd string, inputOS string) (string, error) {
if inputOS == "" {
inputOS = "linux"
}
wd, err := NormalizePath(current, wd, inputOS, false)
if err != nil {
return "", errors.Wrap(err, "normalizing working directory")
}
// Make sure we use the platform specific path separator. HCS does not like forward
// slashes in CWD.
return fromSlash(wd, inputOS), nil
}
// IsAbs returns a boolean value indicating whether or not the path
// is absolute. On Linux, this is just a wrapper for filepath.IsAbs().
// On Windows, we strip away the drive letter (if any), clean the path,
// and check whether or not the path starts with a filepath.Separator.
// This function is meant to check if a path is absolute, in the context
// of a COPY, ADD or WORKDIR, which have their root set in the mount point
// of the writable layer we are mutating. The filepath.IsAbs() function on
// Windows will not work in these scenatios, as it will return true for paths
// that:
// - Begin with drive letter (DOS style paths)
// - Are volume paths \\?\Volume{UUID}
// - Are UNC paths
func IsAbs(pth, inputOS string) bool {
if inputOS == "" {
inputOS = "linux"
}
cleanedPath, err := CheckSystemDriveAndRemoveDriveLetter(pth, inputOS)
if err != nil {
return false
}
cleanedPath = toSlash(cleanedPath, inputOS)
// We stripped any potential drive letter and converted any backslashes to
// forward slashes. We can safely use path.IsAbs() for both Windows and Linux.
return path.IsAbs(cleanedPath)
}
// CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path.
// For linux, this is a no-op.
//
// This is used, for example, when validating a user provided path in docker cp.
// If a drive letter is supplied, it must be the system drive. The drive letter
// is always removed. It also converts any backslash to forward slash. The conversion
// to OS specific separator should happen as late as possible (ie: before passing the
// value to the function that will actually use it). Paths are parsed and code paths are
// triggered starting with the client and all the way down to calling into the runtime
// environment. The client may run on a foreign OS from the one the build will be triggered
// (Windows clients connecting to Linux or vice versa).
// Keeping the file separator consistent until the last moment is desirable.
//
// We need the Windows path without the drive letter so that it can ultimately be concatenated with
// a Windows long-path which doesn't support drive-letters. Examples:
// C: --> Fail
// C:somepath --> somepath // This is a relative path to the CWD set for that drive letter
// C:\ --> \
// a --> a
// /a --> \a
// d:\ --> Fail
//
// UNC paths can refer to multiple types of paths. From local filesystem paths,
// to remote filesystems like SMB or named pipes.
// There is no sane way to support this without adding a lot of complexity
// which I am not sure is worth it.
// \\.\C$\a --> Fail
func CheckSystemDriveAndRemoveDriveLetter(path string, inputOS string) (string, error) {
if inputOS == "" {
inputOS = "linux"
}
if inputOS != "windows" {
return path, nil
}
if len(path) == 2 && string(path[1]) == ":" {
return "", errors.Errorf("No relative path specified in %q", path)
}
// UNC paths should error out
if len(path) >= 2 && toSlash(path[:2], inputOS) == "//" {
return "", errors.Errorf("UNC paths are not supported")
}
parts := strings.SplitN(path, ":", 2)
// Path does not have a drive letter. Just return it.
if len(parts) < 2 {
return toSlash(filepath.Clean(path), inputOS), nil
}
// We expect all paths to be in C:
if !strings.EqualFold(parts[0], "c") {
return "", errors.New("The specified path is not on the system drive (C:)")
}
// A path of the form F:somepath, is a path that is relative CWD set for a particular
// drive letter. See:
// https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file#fully-qualified-vs-relative-paths
//
// C:\>mkdir F:somepath
// C:\>dir F:\
// Volume in drive F is New Volume
// Volume Serial Number is 86E5-AB64
//
// Directory of F:\
//
// 11/27/2022 02:22 PM <DIR> somepath
// 0 File(s) 0 bytes
// 1 Dir(s) 1,052,876,800 bytes free
//
// We must return the second element of the split path, as is, without attempting to convert
// it to an absolute path. We have no knowledge of the CWD; that is treated elsewhere.
return toSlash(filepath.Clean(parts[1]), inputOS), nil
}

View File

@@ -1,10 +0,0 @@
//go:build !windows
// +build !windows
package system
// CheckSystemDriveAndRemoveDriveLetter verifies that a path, if it includes a drive letter,
// is the system drive. This is a no-op on Linux.
func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {
return path, nil
}

View File

@@ -1,35 +0,0 @@
//go:build windows
// +build windows
package system
import (
"path/filepath"
"strings"
"github.com/pkg/errors"
)
// CheckSystemDriveAndRemoveDriveLetter verifies and manipulates a Windows path.
// This is used, for example, when validating a user provided path in docker cp.
// If a drive letter is supplied, it must be the system drive. The drive letter
// is always removed. Also, it translates it to OS semantics (IOW / to \). We
// need the path in this syntax so that it can ultimately be contatenated with
// a Windows long-path which doesn't support drive-letters. Examples:
// C: --> Fail
// C:\ --> \
// a --> a
// /a --> \a
// d:\ --> Fail
func CheckSystemDriveAndRemoveDriveLetter(path string) (string, error) {
if len(path) == 2 && string(path[1]) == ":" {
return "", errors.Errorf("No relative path specified in %q", path)
}
if !filepath.IsAbs(path) || len(path) < 2 {
return filepath.FromSlash(path), nil
}
if string(path[1]) == ":" && !strings.EqualFold(string(path[0]), "c") {
return "", errors.New("The specified path is not on the system drive (C:)")
}
return filepath.FromSlash(path[2:]), nil
}

View File

@@ -181,6 +181,13 @@ func (v *VT100) UsedHeight() int {
} }
func (v *VT100) Resize(y, x int) { func (v *VT100) Resize(y, x int) {
// add some minimal defaults to handle zero and negative values
if x < 6 {
x = 6
}
if y < 1 {
y = 1
}
if y > v.Height { if y > v.Height {
n := y - v.Height n := y - v.Height
for row := 0; row < n; row++ { for row := 0; row < n; row++ {
@@ -329,6 +336,10 @@ func (v *VT100) advance() {
} }
func (v *VT100) scrollIfNeeded() { func (v *VT100) scrollIfNeeded() {
if v.Cursor.X >= v.Width {
v.Cursor.X = 0
v.Cursor.Y++
}
if v.Cursor.Y >= v.Height { if v.Cursor.Y >= v.Height {
first := v.Content[0] first := v.Content[0]
copy(v.Content, v.Content[1:]) copy(v.Content, v.Content[1:])

13
vendor/modules.txt vendored
View File

@@ -147,7 +147,7 @@ github.com/compose-spec/compose-go/utils
# github.com/containerd/console v1.0.3 # github.com/containerd/console v1.0.3
## explicit; go 1.13 ## explicit; go 1.13
github.com/containerd/console github.com/containerd/console
# github.com/containerd/containerd v1.7.1 # github.com/containerd/containerd v1.7.2
## explicit; go 1.19 ## explicit; go 1.19
github.com/containerd/containerd/api/services/content/v1 github.com/containerd/containerd/api/services/content/v1
github.com/containerd/containerd/archive/compression github.com/containerd/containerd/archive/compression
@@ -206,7 +206,7 @@ github.com/davecgh/go-spew/spew
# github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa # github.com/distribution/distribution/v3 v3.0.0-20230214150026-36d8c594d7aa
## explicit; go 1.18 ## explicit; go 1.18
github.com/distribution/distribution/v3/reference github.com/distribution/distribution/v3/reference
# github.com/docker/cli v24.0.1+incompatible # github.com/docker/cli v24.0.2+incompatible
## explicit ## explicit
github.com/docker/cli/cli github.com/docker/cli/cli
github.com/docker/cli/cli-plugins/manager github.com/docker/cli/cli-plugins/manager
@@ -231,7 +231,7 @@ github.com/docker/cli/cli/streams
github.com/docker/cli/cli/trust github.com/docker/cli/cli/trust
github.com/docker/cli/cli/version github.com/docker/cli/cli/version
github.com/docker/cli/opts github.com/docker/cli/opts
# github.com/docker/cli-docs-tool v0.5.1 # github.com/docker/cli-docs-tool v0.6.0
## explicit; go 1.18 ## explicit; go 1.18
github.com/docker/cli-docs-tool github.com/docker/cli-docs-tool
github.com/docker/cli-docs-tool/annotation github.com/docker/cli-docs-tool/annotation
@@ -254,7 +254,7 @@ github.com/docker/distribution/registry/client/transport
github.com/docker/distribution/registry/storage/cache github.com/docker/distribution/registry/storage/cache
github.com/docker/distribution/registry/storage/cache/memory github.com/docker/distribution/registry/storage/cache/memory
github.com/docker/distribution/uuid github.com/docker/distribution/uuid
# github.com/docker/docker v24.0.1+incompatible # github.com/docker/docker v24.0.2+incompatible
## explicit ## explicit
github.com/docker/docker/api github.com/docker/docker/api
github.com/docker/docker/api/types github.com/docker/docker/api/types
@@ -498,7 +498,7 @@ github.com/mitchellh/go-wordwrap
# github.com/mitchellh/mapstructure v1.5.0 # github.com/mitchellh/mapstructure v1.5.0
## explicit; go 1.14 ## explicit; go 1.14
github.com/mitchellh/mapstructure github.com/mitchellh/mapstructure
# github.com/moby/buildkit v0.11.0-rc3.0.20230530080511-c36941f4a10e # github.com/moby/buildkit v0.11.0-rc3.0.20230609092854-67a08623b95a
## explicit; go 1.20 ## explicit; go 1.20
github.com/moby/buildkit/api/services/control github.com/moby/buildkit/api/services/control
github.com/moby/buildkit/api/types github.com/moby/buildkit/api/types
@@ -513,6 +513,7 @@ github.com/moby/buildkit/client/ociindex
github.com/moby/buildkit/cmd/buildkitd/config github.com/moby/buildkit/cmd/buildkitd/config
github.com/moby/buildkit/exporter/containerimage/exptypes github.com/moby/buildkit/exporter/containerimage/exptypes
github.com/moby/buildkit/exporter/containerimage/image github.com/moby/buildkit/exporter/containerimage/image
github.com/moby/buildkit/exporter/exptypes
github.com/moby/buildkit/frontend/attestations github.com/moby/buildkit/frontend/attestations
github.com/moby/buildkit/frontend/dockerfile/dockerignore github.com/moby/buildkit/frontend/dockerfile/dockerignore
github.com/moby/buildkit/frontend/dockerui github.com/moby/buildkit/frontend/dockerui
@@ -691,7 +692,7 @@ github.com/tonistiigi/fsutil/types
# github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea # github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea
## explicit ## explicit
github.com/tonistiigi/units github.com/tonistiigi/units
# github.com/tonistiigi/vt100 v0.0.0-20210615222946-8066bb97264f # github.com/tonistiigi/vt100 v0.0.0-20230623042737-f9a4f7ef6531
## explicit; go 1.12 ## explicit; go 1.12
github.com/tonistiigi/vt100 github.com/tonistiigi/vt100
# github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f # github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f