Skip to content

Commit fea7459

Browse files
committed
history: add history import command
Signed-off-by: Tonis Tiigi <[email protected]>
1 parent e2d52a8 commit fea7459

File tree

8 files changed

+180
-0
lines changed

8 files changed

+180
-0
lines changed

commands/history/import.go

+102
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
package history
2+
3+
import (
4+
"context"
5+
"encoding/json"
6+
"fmt"
7+
"io"
8+
"net"
9+
"net/http"
10+
"os"
11+
"strings"
12+
13+
remoteutil "github.com/docker/buildx/driver/remote/util"
14+
"github.com/docker/buildx/util/cobrautil/completion"
15+
"github.com/docker/buildx/util/desktop"
16+
"github.com/docker/cli/cli/command"
17+
"github.com/pkg/browser"
18+
"github.com/pkg/errors"
19+
"github.com/spf13/cobra"
20+
)
21+
22+
type importOptions struct {
23+
file string
24+
}
25+
26+
func runImport(ctx context.Context, _ command.Cli, opts importOptions) error {
27+
sock, err := desktop.BuildServerAddr()
28+
if err != nil {
29+
return err
30+
}
31+
32+
tr := http.DefaultTransport.(*http.Transport).Clone()
33+
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) {
34+
network, addr, ok := strings.Cut(sock, "://")
35+
if !ok {
36+
return nil, errors.Errorf("invalid endpoint address: %s", sock)
37+
}
38+
return remoteutil.DialContext(ctx, network, addr)
39+
}
40+
41+
client := &http.Client{
42+
Transport: tr,
43+
}
44+
45+
var rdr io.Reader = os.Stdin
46+
if opts.file != "" {
47+
f, err := os.Open(opts.file)
48+
if err != nil {
49+
return errors.Wrap(err, "failed to open file")
50+
}
51+
defer f.Close()
52+
rdr = f
53+
}
54+
55+
req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://docker-desktop/upload", rdr)
56+
if err != nil {
57+
return errors.Wrap(err, "failed to create request")
58+
}
59+
60+
resp, err := client.Do(req)
61+
if err != nil {
62+
return errors.Wrap(err, "failed to send request, check if Docker Desktop is running")
63+
}
64+
defer resp.Body.Close()
65+
66+
if resp.StatusCode != http.StatusOK {
67+
body, _ := io.ReadAll(resp.Body)
68+
return errors.Errorf("failed to import build: %s", string(body))
69+
}
70+
71+
var refs []string
72+
dec := json.NewDecoder(resp.Body)
73+
if err := dec.Decode(&refs); err != nil {
74+
return errors.Wrap(err, "failed to decode response")
75+
}
76+
77+
if len(refs) == 0 {
78+
return errors.New("no build records found in the bundle")
79+
}
80+
81+
url := desktop.BuildURL(fmt.Sprintf(".imported/_/%s", refs[0]))
82+
return browser.OpenURL(url)
83+
}
84+
85+
func importCmd(dockerCli command.Cli, _ RootOptions) *cobra.Command {
86+
var options importOptions
87+
88+
cmd := &cobra.Command{
89+
Use: "import [OPTIONS] < bundle.dockerbuild",
90+
Short: "Import a build into Docker Desktop",
91+
Args: cobra.NoArgs,
92+
RunE: func(cmd *cobra.Command, args []string) error {
93+
return runImport(cmd.Context(), dockerCli, options)
94+
},
95+
ValidArgsFunction: completion.Disable,
96+
}
97+
98+
flags := cmd.Flags()
99+
flags.StringVarP(&options.file, "file", "f", "", "Import from a file path")
100+
101+
return cmd
102+
}

commands/history/root.go

+1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ func RootCmd(rootcmd *cobra.Command, dockerCli command.Cli, opts RootOptions) *c
2525
inspectCmd(dockerCli, opts),
2626
openCmd(dockerCli, opts),
2727
traceCmd(dockerCli, opts),
28+
importCmd(dockerCli, opts),
2829
)
2930

3031
return cmd

docs/reference/buildx_history.md

+1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ Commands to work on build records
77

88
| Name | Description |
99
|:---------------------------------------|:-----------------------------------------------|
10+
| [`import`](buildx_history_import.md) | Import a build into Docker Desktop |
1011
| [`inspect`](buildx_history_inspect.md) | Inspect a build |
1112
| [`logs`](buildx_history_logs.md) | Print the logs of a build |
1213
| [`ls`](buildx_history_ls.md) | List build records |
+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# docker buildx history import
2+
3+
<!---MARKER_GEN_START-->
4+
Import a build into Docker Desktop
5+
6+
### Options
7+
8+
| Name | Type | Default | Description |
9+
|:----------------|:---------|:--------|:-----------------------------------------|
10+
| `--builder` | `string` | | Override the configured builder instance |
11+
| `-D`, `--debug` | `bool` | | Enable debug logging |
12+
| `-f`, `--file` | `string` | | Import from a file path |
13+
14+
15+
<!---MARKER_GEN_END-->
16+

util/desktop/paths_darwin.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package desktop
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
7+
"github.com/pkg/errors"
8+
)
9+
10+
const (
11+
socketName = "docker-desktop-build.sock"
12+
socketPath = "Library/Containers/com.docker.docker/Data"
13+
)
14+
15+
func BuildServerAddr() (string, error) {
16+
dir, err := os.UserHomeDir()
17+
if err != nil {
18+
return "", errors.Wrap(err, "failed to get user home directory")
19+
}
20+
return "unix://" + filepath.Join(dir, socketPath, socketName), nil
21+
}

util/desktop/paths_linux.go

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package desktop
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
7+
"github.com/pkg/errors"
8+
)
9+
10+
const (
11+
socketName = "docker-desktop-build.sock"
12+
socketPath = ".docker/desktop"
13+
)
14+
15+
func BuildServerAddr() (string, error) {
16+
dir, err := os.UserHomeDir()
17+
if err != nil {
18+
return "", errors.Wrap(err, "failed to get user home directory")
19+
}
20+
return "unix://" + filepath.Join(dir, socketPath, socketName), nil
21+
}

util/desktop/paths_unsupported.go

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//go:build !windows && !darwin && !linux
2+
3+
package desktop
4+
5+
import (
6+
"runtime"
7+
8+
"github.com/pkg/errors"
9+
)
10+
11+
func BuildServerAddr() (string, error) {
12+
return "", errors.Errorf("Docker Desktop unsupported on %s", runtime.GOOS)
13+
}

util/desktop/paths_windows.go

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
package desktop
2+
3+
func BuildServerAddr() (string, error) {
4+
return "npipe:////./pipe/dockerDesktopBuildServer", nil
5+
}

0 commit comments

Comments
 (0)