Compare commits

..

7 Commits

Author SHA1 Message Date
CrazyMax
4e547752af Merge pull request #1977 from dvdksn/docs/cherrypick_fup_buildinfo
[0.11 backport] docs: update since buildinfo removal
2023-07-31 11:16:47 +02:00
CrazyMax
95eee3e747 docs: update since buildinfo removal
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 8ad30d0a35)
Signed-off-by: David Karlsson <35727626+dvdksn@users.noreply.github.com>
2023-07-31 10:59:33 +02:00
CrazyMax
d5bfd8334f Merge pull request #1960 from thaJeztah/0.11_backport_update_cli
[0.11 backport] vendor: github.com/docker/cli v24.0.4
2023-07-19 12:42:41 +02:00
CrazyMax
2083f24938 Merge pull request #1962 from crazy-max/v0.11_backport_fix-internal-build
[0.11 backport] build: set remote bake def and remote dockerfile as internal solve
2023-07-19 12:42:01 +02:00
CrazyMax
84da4ec603 build: set remote bake def and remote dockerfile as internal solve
Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
(cherry picked from commit 05ef20b434)
2023-07-19 11:55:09 +02:00
Sebastiaan van Stijn
35dac12ae5 commands: NewRootCmd: remove obsolete logrus filter hook
This hook was added in 278f94a8b6 and
72758fef22 to suppress spurious warnings
printed by the CLI's cli/connhelper/commandconn package;
3fb4fb83df/cli/connhelper/commandconn/commandconn.go (L203-L214)

Those logs were removed in a5ebe2282a
so we can remove the hook.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit 094d1aded8)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-07-19 11:05:40 +02:00
Sebastiaan van Stijn
27f332f135 vendor: github.com/docker/cli v24.0.4
full diff: https://github.com/docker/cli/compare/v24.0.2...v24.0.4

notable changes:

- ssh: fix error on commandconn close, add ping and default
- commandconn: return original error while closing

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
(cherry picked from commit cc718b3444)
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2023-07-18 17:17:31 +02:00
10 changed files with 130 additions and 157 deletions

View File

@@ -59,7 +59,7 @@ func ReadRemoteFiles(ctx context.Context, nodes []builder.Node, url string, name
ch, done := progress.NewChannel(pw) ch, done := progress.NewChannel(pw)
defer func() { <-done }() defer func() { <-done }()
_, err = c.Build(ctx, client.SolveOpt{Session: session}, "buildx", func(ctx context.Context, c gwclient.Client) (*gwclient.Result, error) { _, err = c.Build(ctx, client.SolveOpt{Session: session, Internal: true}, "buildx", func(ctx context.Context, c gwclient.Client) (*gwclient.Result, error) {
def, err := st.Marshal(ctx) def, err := st.Marshal(ctx)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -21,7 +21,7 @@ func createTempDockerfileFromURL(ctx context.Context, d *driver.DriverHandle, ur
var out string var out string
ch, done := progress.NewChannel(pw) ch, done := progress.NewChannel(pw)
defer func() { <-done }() defer func() { <-done }()
_, err = c.Build(ctx, client.SolveOpt{}, "buildx", func(ctx context.Context, c gwclient.Client) (*gwclient.Result, error) { _, err = c.Build(ctx, client.SolveOpt{Internal: true}, "buildx", func(ctx context.Context, c gwclient.Client) (*gwclient.Result, error) {
def, err := llb.HTTP(url, llb.Filename("Dockerfile"), llb.WithCustomNamef("[internal] load %s", url)).Marshal(ctx) def, err := llb.HTTP(url, llb.Filename("Dockerfile"), llb.WithCustomNamef("[internal] load %s", url)).Marshal(ctx)
if err != nil { if err != nil {
return nil, err return nil, err

View File

@@ -52,17 +52,6 @@ func NewRootCmd(name string, isPlugin bool, dockerCli command.Cli) *cobra.Comman
"using default config store", "using default config store",
)) ))
// filter out useless commandConn.CloseWrite warning message that can occur
// when listing builder instances with "buildx ls" for those that are
// unreachable: "commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
// https://github.com/docker/cli/blob/3fb4fb83dfb5db0c0753a8316f21aea54dab32c5/cli/connhelper/commandconn/commandconn.go#L203-L214
logrus.AddHook(logutil.NewFilter([]logrus.Level{
logrus.WarnLevel,
},
"commandConn.CloseWrite:",
"commandConn.CloseRead:",
))
addCommands(cmd, dockerCli) addCommands(cmd, dockerCli)
return cmd return cmd
} }

View File

@@ -125,7 +125,6 @@ Same as [`docker build` command](https://docs.docker.com/engine/reference/comman
There are also useful built-in build args like: There are also useful built-in build args like:
* `BUILDKIT_CONTEXT_KEEP_GIT_DIR=<bool>` trigger git context to keep the `.git` directory * `BUILDKIT_CONTEXT_KEEP_GIT_DIR=<bool>` trigger git context to keep the `.git` directory
* `BUILDKIT_INLINE_BUILDINFO_ATTRS=<bool>` inline build info attributes in image config or not
* `BUILDKIT_INLINE_CACHE=<bool>` inline cache metadata to image config or not * `BUILDKIT_INLINE_CACHE=<bool>` inline cache metadata to image config or not
* `BUILDKIT_MULTI_PLATFORM=<bool>` opt into deterministic output regardless of multi-platform output or not * `BUILDKIT_MULTI_PLATFORM=<bool>` opt into deterministic output regardless of multi-platform output or not
@@ -286,26 +285,6 @@ $ cat metadata.json
``` ```
```json ```json
{ {
"containerimage.buildinfo": {
"frontend": "dockerfile.v0",
"attrs": {
"context": "https://github.com/crazy-max/buildkit-buildsources-test.git#master",
"filename": "Dockerfile",
"source": "docker/dockerfile:master"
},
"sources": [
{
"type": "docker-image",
"ref": "docker.io/docker/buildx-bin:0.6.1@sha256:a652ced4a4141977c7daaed0a074dcd9844a78d7d2615465b12f433ae6dd29f0",
"pin": "sha256:a652ced4a4141977c7daaed0a074dcd9844a78d7d2615465b12f433ae6dd29f0"
},
{
"type": "docker-image",
"ref": "docker.io/library/alpine:3.13",
"pin": "sha256:026f721af4cf2843e07bba648e158fb35ecc876d822130633cc49f707f0fc88c"
}
]
},
"containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66", "containerimage.config.digest": "sha256:2937f66a9722f7f4a2df583de2f8cb97fc9196059a410e7f00072fc918930e66",
"containerimage.descriptor": { "containerimage.descriptor": {
"annotations": { "annotations": {

2
go.mod
View File

@@ -10,7 +10,7 @@ require (
github.com/containerd/containerd v1.7.2 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.2+incompatible github.com/docker/cli v24.0.4+incompatible
github.com/docker/cli-docs-tool v0.6.0 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.5-0.20230714235725-36e9e796c6fc+incompatible // 24.0 github.com/docker/docker v24.0.5-0.20230714235725-36e9e796c6fc+incompatible // 24.0

4
go.sum
View File

@@ -149,8 +149,8 @@ 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.2+incompatible h1:QdqR7znue1mtkXIJ+ruQMGQhpw2JzMJLRXp6zpzF6tM= github.com/docker/cli v24.0.4+incompatible h1:Y3bYF9ekNTm2VFz5U/0BlMdJy73D+Y1iAAZ8l63Ydzw=
github.com/docker/cli v24.0.2+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v24.0.4+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8=
github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA= github.com/docker/cli-docs-tool v0.6.0 h1:Z9x10SaZgFaB6jHgz3OWooynhSa40CsWkpe5hEnG/qA=
github.com/docker/cli-docs-tool v0.6.0/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=

View File

@@ -8,7 +8,6 @@ import (
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings"
"sync" "sync"
"time" "time"
@@ -327,13 +326,8 @@ func (cli *DockerCli) getInitTimeout() time.Duration {
func (cli *DockerCli) initializeFromClient() { func (cli *DockerCli) initializeFromClient() {
ctx := context.Background() ctx := context.Background()
if !strings.HasPrefix(cli.dockerEndpoint.Host, "ssh://") { ctx, cancel := context.WithTimeout(ctx, cli.getInitTimeout())
// @FIXME context.WithTimeout doesn't work with connhelper / ssh connections defer cancel()
// time="2020-04-10T10:16:26Z" level=warning msg="commandConn.CloseWrite: commandconn: failed to wait: signal: killed"
var cancel func()
ctx, cancel = context.WithTimeout(ctx, cli.getInitTimeout())
defer cancel()
}
ping, err := cli.client.Ping(ctx) ping, err := cli.client.Ping(ctx)
if err != nil { if err != nil {
@@ -381,7 +375,7 @@ func (cli *DockerCli) ContextStore() store.Store {
// the "default" context is used if: // the "default" context is used if:
// //
// - The "--host" option is set // - The "--host" option is set
// - The "DOCKER_HOST" ([DefaultContextName]) environment variable is set // - The "DOCKER_HOST" ([client.EnvOverrideHost]) environment variable is set
// to a non-empty value. // to a non-empty value.
// //
// In these cases, the default context is used, which uses the host as // In these cases, the default context is used, which uses the host as

View File

@@ -23,6 +23,7 @@ import (
"runtime" "runtime"
"strings" "strings"
"sync" "sync"
"sync/atomic"
"syscall" "syscall"
"time" "time"
@@ -64,81 +65,68 @@ func New(_ context.Context, cmd string, args ...string) (net.Conn, error) {
// commandConn implements net.Conn // commandConn implements net.Conn
type commandConn struct { type commandConn struct {
cmd *exec.Cmd cmdMutex sync.Mutex // for cmd, cmdWaitErr
cmdExited bool cmd *exec.Cmd
cmdWaitErr error cmdWaitErr error
cmdMutex sync.Mutex cmdExited atomic.Bool
stdin io.WriteCloser stdin io.WriteCloser
stdout io.ReadCloser stdout io.ReadCloser
stderrMu sync.Mutex stderrMu sync.Mutex // for stderr
stderr bytes.Buffer stderr bytes.Buffer
stdioClosedMu sync.Mutex // for stdinClosed and stdoutClosed stdinClosed atomic.Bool
stdinClosed bool stdoutClosed atomic.Bool
stdoutClosed bool closing atomic.Bool
localAddr net.Addr localAddr net.Addr
remoteAddr net.Addr remoteAddr net.Addr
} }
// killIfStdioClosed kills the cmd if both stdin and stdout are closed. // kill terminates the process. On Windows it kills the process directly,
func (c *commandConn) killIfStdioClosed() error { // whereas on other platforms, a SIGTERM is sent, before forcefully terminating
c.stdioClosedMu.Lock() // the process after 3 seconds.
stdioClosed := c.stdoutClosed && c.stdinClosed func (c *commandConn) kill() {
c.stdioClosedMu.Unlock() if c.cmdExited.Load() {
if !stdioClosed { return
return nil
} }
return c.kill() c.cmdMutex.Lock()
}
// killAndWait tries sending SIGTERM to the process before sending SIGKILL.
func killAndWait(cmd *exec.Cmd) error {
var werr error var werr error
if runtime.GOOS != "windows" { if runtime.GOOS != "windows" {
werrCh := make(chan error) werrCh := make(chan error)
go func() { werrCh <- cmd.Wait() }() go func() { werrCh <- c.cmd.Wait() }()
cmd.Process.Signal(syscall.SIGTERM) _ = c.cmd.Process.Signal(syscall.SIGTERM)
select { select {
case werr = <-werrCh: case werr = <-werrCh:
case <-time.After(3 * time.Second): case <-time.After(3 * time.Second):
cmd.Process.Kill() _ = c.cmd.Process.Kill()
werr = <-werrCh werr = <-werrCh
} }
} else { } else {
cmd.Process.Kill() _ = c.cmd.Process.Kill()
werr = cmd.Wait() werr = c.cmd.Wait()
}
return werr
}
// kill returns nil if the command terminated, regardless to the exit status.
func (c *commandConn) kill() error {
var werr error
c.cmdMutex.Lock()
if c.cmdExited {
werr = c.cmdWaitErr
} else {
werr = killAndWait(c.cmd)
c.cmdWaitErr = werr
c.cmdExited = true
} }
c.cmdWaitErr = werr
c.cmdMutex.Unlock() c.cmdMutex.Unlock()
if werr == nil { c.cmdExited.Store(true)
return nil
}
wExitErr, ok := werr.(*exec.ExitError)
if ok {
if wExitErr.ProcessState.Exited() {
return nil
}
}
return errors.Wrapf(werr, "commandconn: failed to wait")
} }
func (c *commandConn) onEOF(eof error) error { // handleEOF handles io.EOF errors while reading or writing from the underlying
// when we got EOF, the command is going to be terminated // command pipes.
var werr error //
// When we've received an EOF we expect that the command will
// be terminated soon. As such, we call Wait() on the command
// and return EOF or the error depending on whether the command
// exited with an error.
//
// If Wait() does not return within 10s, an error is returned
func (c *commandConn) handleEOF(err error) error {
if err != io.EOF {
return err
}
c.cmdMutex.Lock() c.cmdMutex.Lock()
if c.cmdExited { defer c.cmdMutex.Unlock()
var werr error
if c.cmdExited.Load() {
werr = c.cmdWaitErr werr = c.cmdWaitErr
} else { } else {
werrCh := make(chan error) werrCh := make(chan error)
@@ -146,18 +134,17 @@ func (c *commandConn) onEOF(eof error) error {
select { select {
case werr = <-werrCh: case werr = <-werrCh:
c.cmdWaitErr = werr c.cmdWaitErr = werr
c.cmdExited = true c.cmdExited.Store(true)
case <-time.After(10 * time.Second): case <-time.After(10 * time.Second):
c.cmdMutex.Unlock()
c.stderrMu.Lock() c.stderrMu.Lock()
stderr := c.stderr.String() stderr := c.stderr.String()
c.stderrMu.Unlock() c.stderrMu.Unlock()
return errors.Errorf("command %v did not exit after %v: stderr=%q", c.cmd.Args, eof, stderr) return errors.Errorf("command %v did not exit after %v: stderr=%q", c.cmd.Args, err, stderr)
} }
} }
c.cmdMutex.Unlock()
if werr == nil { if werr == nil {
return eof return err
} }
c.stderrMu.Lock() c.stderrMu.Lock()
stderr := c.stderr.String() stderr := c.stderr.String()
@@ -166,71 +153,86 @@ func (c *commandConn) onEOF(eof error) error {
} }
func ignorableCloseError(err error) bool { func ignorableCloseError(err error) bool {
errS := err.Error() return strings.Contains(err.Error(), os.ErrClosed.Error())
ss := []string{
os.ErrClosed.Error(),
}
for _, s := range ss {
if strings.Contains(errS, s) {
return true
}
}
return false
}
func (c *commandConn) CloseRead() error {
// NOTE: maybe already closed here
if err := c.stdout.Close(); err != nil && !ignorableCloseError(err) {
logrus.Warnf("commandConn.CloseRead: %v", err)
}
c.stdioClosedMu.Lock()
c.stdoutClosed = true
c.stdioClosedMu.Unlock()
if err := c.killIfStdioClosed(); err != nil {
logrus.Warnf("commandConn.CloseRead: %v", err)
}
return nil
} }
func (c *commandConn) Read(p []byte) (int, error) { func (c *commandConn) Read(p []byte) (int, error) {
n, err := c.stdout.Read(p) n, err := c.stdout.Read(p)
if err == io.EOF { // check after the call to Read, since
err = c.onEOF(err) // it is blocking, and while waiting on it
// Close might get called
if c.closing.Load() {
// If we're currently closing the connection
// we don't want to call onEOF
return n, err
} }
return n, err
}
func (c *commandConn) CloseWrite() error { return n, c.handleEOF(err)
// NOTE: maybe already closed here
if err := c.stdin.Close(); err != nil && !ignorableCloseError(err) {
logrus.Warnf("commandConn.CloseWrite: %v", err)
}
c.stdioClosedMu.Lock()
c.stdinClosed = true
c.stdioClosedMu.Unlock()
if err := c.killIfStdioClosed(); err != nil {
logrus.Warnf("commandConn.CloseWrite: %v", err)
}
return nil
} }
func (c *commandConn) Write(p []byte) (int, error) { func (c *commandConn) Write(p []byte) (int, error) {
n, err := c.stdin.Write(p) n, err := c.stdin.Write(p)
if err == io.EOF { // check after the call to Write, since
err = c.onEOF(err) // it is blocking, and while waiting on it
// Close might get called
if c.closing.Load() {
// If we're currently closing the connection
// we don't want to call onEOF
return n, err
} }
return n, err
return n, c.handleEOF(err)
} }
// CloseRead allows commandConn to implement halfCloser
func (c *commandConn) CloseRead() error {
// NOTE: maybe already closed here
if err := c.stdout.Close(); err != nil && !ignorableCloseError(err) {
return err
}
c.stdoutClosed.Store(true)
if c.stdinClosed.Load() {
c.kill()
}
return nil
}
// CloseWrite allows commandConn to implement halfCloser
func (c *commandConn) CloseWrite() error {
// NOTE: maybe already closed here
if err := c.stdin.Close(); err != nil && !ignorableCloseError(err) {
return err
}
c.stdinClosed.Store(true)
if c.stdoutClosed.Load() {
c.kill()
}
return nil
}
// Close is the net.Conn func that gets called
// by the transport when a dial is cancelled
// due to it's context timing out. Any blocked
// Read or Write calls will be unblocked and
// return errors. It will block until the underlying
// command has terminated.
func (c *commandConn) Close() error { func (c *commandConn) Close() error {
var err error c.closing.Store(true)
if err = c.CloseRead(); err != nil { defer c.closing.Store(false)
if err := c.CloseRead(); err != nil {
logrus.Warnf("commandConn.Close: CloseRead: %v", err) logrus.Warnf("commandConn.Close: CloseRead: %v", err)
return err
} }
if err = c.CloseWrite(); err != nil { if err := c.CloseWrite(); err != nil {
logrus.Warnf("commandConn.Close: CloseWrite: %v", err) logrus.Warnf("commandConn.Close: CloseWrite: %v", err)
return err
} }
return err
return nil
} }
func (c *commandConn) LocalAddr() net.Addr { func (c *commandConn) LocalAddr() net.Addr {

View File

@@ -5,6 +5,7 @@ import (
"context" "context"
"net" "net"
"net/url" "net/url"
"strings"
"github.com/docker/cli/cli/connhelper/commandconn" "github.com/docker/cli/cli/connhelper/commandconn"
"github.com/docker/cli/cli/connhelper/ssh" "github.com/docker/cli/cli/connhelper/ssh"
@@ -51,6 +52,7 @@ func getConnectionHelper(daemonURL string, sshFlags []string) (*ConnectionHelper
if sp.Path != "" { if sp.Path != "" {
args = append(args, "--host", "unix://"+sp.Path) args = append(args, "--host", "unix://"+sp.Path)
} }
sshFlags = addSSHTimeout(sshFlags)
args = append(args, "system", "dial-stdio") args = append(args, "system", "dial-stdio")
return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...) return commandconn.New(ctx, "ssh", append(sshFlags, sp.Args(args...)...)...)
}, },
@@ -71,3 +73,10 @@ func GetCommandConnectionHelper(cmd string, flags ...string) (*ConnectionHelper,
Host: "http://docker.example.com", Host: "http://docker.example.com",
}, nil }, nil
} }
func addSSHTimeout(sshFlags []string) []string {
if !strings.Contains(strings.Join(sshFlags, ""), "ConnectTimeout") {
sshFlags = append(sshFlags, "-o ConnectTimeout=30")
}
return sshFlags
}

2
vendor/modules.txt vendored
View File

@@ -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.2+incompatible # github.com/docker/cli v24.0.4+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