-
Notifications
You must be signed in to change notification settings - Fork 510
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #3039 from tonistiigi/history-import
history: add history import command
- Loading branch information
Showing
8 changed files
with
221 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
package history | ||
|
||
import ( | ||
"context" | ||
"encoding/json" | ||
"fmt" | ||
"io" | ||
"net" | ||
"net/http" | ||
"os" | ||
"strings" | ||
|
||
remoteutil "github.com/docker/buildx/driver/remote/util" | ||
"github.com/docker/buildx/util/cobrautil/completion" | ||
"github.com/docker/buildx/util/desktop" | ||
"github.com/docker/cli/cli/command" | ||
"github.com/pkg/browser" | ||
"github.com/pkg/errors" | ||
"github.com/spf13/cobra" | ||
) | ||
|
||
type importOptions struct { | ||
file []string | ||
} | ||
|
||
func runImport(ctx context.Context, dockerCli command.Cli, opts importOptions) error { | ||
sock, err := desktop.BuildServerAddr() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
tr := http.DefaultTransport.(*http.Transport).Clone() | ||
tr.DialContext = func(ctx context.Context, _, _ string) (net.Conn, error) { | ||
network, addr, ok := strings.Cut(sock, "://") | ||
if !ok { | ||
return nil, errors.Errorf("invalid endpoint address: %s", sock) | ||
} | ||
return remoteutil.DialContext(ctx, network, addr) | ||
} | ||
|
||
client := &http.Client{ | ||
Transport: tr, | ||
} | ||
|
||
var urls []string | ||
|
||
if len(opts.file) == 0 { | ||
u, err := importFrom(ctx, client, os.Stdin) | ||
if err != nil { | ||
return err | ||
} | ||
urls = append(urls, u...) | ||
} else { | ||
for _, fn := range opts.file { | ||
var f *os.File | ||
var rdr io.Reader = os.Stdin | ||
if fn != "-" { | ||
f, err = os.Open(fn) | ||
if err != nil { | ||
return errors.Wrapf(err, "failed to open file %s", fn) | ||
} | ||
rdr = f | ||
} | ||
u, err := importFrom(ctx, client, rdr) | ||
if err != nil { | ||
return err | ||
} | ||
urls = append(urls, u...) | ||
if f != nil { | ||
f.Close() | ||
} | ||
} | ||
} | ||
|
||
if len(urls) == 0 { | ||
return errors.New("no build records found in the bundle") | ||
} | ||
|
||
for i, url := range urls { | ||
fmt.Fprintln(dockerCli.Err(), url) | ||
if i == 0 { | ||
err = browser.OpenURL(url) | ||
} | ||
} | ||
return err | ||
} | ||
|
||
func importFrom(ctx context.Context, c *http.Client, rdr io.Reader) ([]string, error) { | ||
req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://docker-desktop/upload", rdr) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to create request") | ||
} | ||
|
||
resp, err := c.Do(req) | ||
if err != nil { | ||
return nil, errors.Wrap(err, "failed to send request, check if Docker Desktop is running") | ||
} | ||
defer resp.Body.Close() | ||
|
||
if resp.StatusCode != http.StatusOK { | ||
body, _ := io.ReadAll(resp.Body) | ||
return nil, errors.Errorf("failed to import build: %s", string(body)) | ||
} | ||
|
||
var refs []string | ||
dec := json.NewDecoder(resp.Body) | ||
if err := dec.Decode(&refs); err != nil { | ||
return nil, errors.Wrap(err, "failed to decode response") | ||
} | ||
|
||
var urls []string | ||
for _, ref := range refs { | ||
urls = append(urls, desktop.BuildURL(fmt.Sprintf(".imported/_/%s", ref))) | ||
} | ||
return urls, err | ||
} | ||
|
||
func importCmd(dockerCli command.Cli, _ RootOptions) *cobra.Command { | ||
var options importOptions | ||
|
||
cmd := &cobra.Command{ | ||
Use: "import [OPTIONS] < bundle.dockerbuild", | ||
Short: "Import a build into Docker Desktop", | ||
Args: cobra.NoArgs, | ||
RunE: func(cmd *cobra.Command, args []string) error { | ||
return runImport(cmd.Context(), dockerCli, options) | ||
}, | ||
ValidArgsFunction: completion.Disable, | ||
} | ||
|
||
flags := cmd.Flags() | ||
flags.StringArrayVarP(&options.file, "file", "f", nil, "Import from a file path") | ||
|
||
return cmd | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
# docker buildx history import | ||
|
||
<!---MARKER_GEN_START--> | ||
Import a build into Docker Desktop | ||
|
||
### Options | ||
|
||
| Name | Type | Default | Description | | ||
|:----------------|:--------------|:--------|:-----------------------------------------| | ||
| `--builder` | `string` | | Override the configured builder instance | | ||
| `-D`, `--debug` | `bool` | | Enable debug logging | | ||
| `-f`, `--file` | `stringArray` | | Import from a file path | | ||
|
||
|
||
<!---MARKER_GEN_END--> | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package desktop | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
const ( | ||
socketName = "docker-desktop-build.sock" | ||
socketPath = "Library/Containers/com.docker.docker/Data" | ||
) | ||
|
||
func BuildServerAddr() (string, error) { | ||
dir, err := os.UserHomeDir() | ||
if err != nil { | ||
return "", errors.Wrap(err, "failed to get user home directory") | ||
} | ||
return "unix://" + filepath.Join(dir, socketPath, socketName), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
package desktop | ||
|
||
import ( | ||
"os" | ||
"path/filepath" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
const ( | ||
socketName = "docker-desktop-build.sock" | ||
socketPath = ".docker/desktop" | ||
wslSocketPath = "/mnt/wsl/docker-desktop/shared-sockets/host-services" | ||
) | ||
|
||
func BuildServerAddr() (string, error) { | ||
if os.Getenv("WSL_DISTRO_NAME") != "" { | ||
socket := filepath.Join(wslSocketPath, socketName) | ||
if _, err := os.Stat(socket); os.IsNotExist(err) { | ||
return "", errors.New("Docker Desktop Build backend is not yet supported on WSL. Please run this command on Windows host instead.") //nolint:revive | ||
} | ||
return "unix://" + socket, nil | ||
} | ||
dir, err := os.UserHomeDir() | ||
if err != nil { | ||
return "", errors.Wrap(err, "failed to get user home directory") | ||
} | ||
return "unix://" + filepath.Join(dir, socketPath, socketName), nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
//go:build !windows && !darwin && !linux | ||
|
||
package desktop | ||
|
||
import ( | ||
"runtime" | ||
|
||
"github.com/pkg/errors" | ||
) | ||
|
||
func BuildServerAddr() (string, error) { | ||
return "", errors.Errorf("Docker Desktop unsupported on %s", runtime.GOOS) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
package desktop | ||
|
||
func BuildServerAddr() (string, error) { | ||
return "npipe:////./pipe/dockerDesktopBuildServer", nil | ||
} |