Compare commits

...

19 Commits

Author SHA1 Message Date
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
32 changed files with 410 additions and 129 deletions

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

@@ -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

@@ -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 {
@@ -704,6 +704,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 +724,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 +750,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

@@ -47,7 +47,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
}, },

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

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

@@ -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,36 @@ 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
} }
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
}

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,
} }
} }

8
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.5.1
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

19
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.5.1 h1:jIk/cCZurZERhALPVKhqlNxTQGxn2kcI+56gE57PQXg=
github.com/docker/cli-docs-tool v0.5.1/go.mod h1:zMjqTFCU361PRh8apiXzeAZ1Q/xupbIwTusYpzCXS/o= github.com/docker/cli-docs-tool v0.5.1/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=

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

@@ -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

@@ -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

@@ -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 _, exists := ap.authConfigCache[host]; !exists {
if host == "registry-1.docker.io" { if host == dockerHubRegistryHost {
host = "https://index.docker.io/v1/" host = dockerHubConfigfileKey
} }
if _, exists := ap.authConfigCache[host]; !exists {
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
}

9
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
@@ -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