build: fix localstate for remote context and stdin

Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2024-06-28 09:54:23 +02:00
parent d4b112ab05
commit cfb7fc4fb5
No known key found for this signature in database
GPG Key ID: ADE44D8C9D44FBE4
4 changed files with 175 additions and 24 deletions

View File

@ -15,29 +15,29 @@ func saveLocalState(so *client.SolveOpt, target string, opts Options, node build
}
lp := opts.Inputs.ContextPath
dp := opts.Inputs.DockerfilePath
if lp != "" || dp != "" {
if lp != "" {
lp, err = filepath.Abs(lp)
if err != nil {
return err
}
}
if dp != "" {
dp, err = filepath.Abs(dp)
if err != nil {
return err
}
}
l, err := localstate.New(configDir)
if dp != "" && !IsRemoteURL(lp) && lp != "-" && dp != "-" {
dp, err = filepath.Abs(dp)
if err != nil {
return err
}
return l.SaveRef(node.Builder, node.Name, so.Ref, localstate.State{
Target: target,
LocalPath: lp,
DockerfilePath: dp,
GroupRef: opts.GroupRef,
})
}
return nil
if lp != "" && !IsRemoteURL(lp) && lp != "-" {
lp, err = filepath.Abs(lp)
if err != nil {
return err
}
}
if lp == "" && dp == "" {
return nil
}
l, err := localstate.New(configDir)
if err != nil {
return err
}
return l.SaveRef(node.Builder, node.Name, so.Ref, localstate.State{
Target: target,
LocalPath: lp,
DockerfilePath: dp,
GroupRef: opts.GroupRef,
})
}

View File

@ -21,9 +21,10 @@ const (
type State struct {
// Target is the name of the invoked target (default if empty)
Target string
// LocalPath is the absolute path to the context
// LocalPath is the absolute path to the context or remote context
LocalPath string
// DockerfilePath is the absolute path to the Dockerfile
// DockerfilePath is the absolute path to the Dockerfile or relative if
// context is remote
DockerfilePath string
// GroupRef is the ref of the state group that this ref belongs to
GroupRef string `json:",omitempty"`

View File

@ -16,6 +16,7 @@ import (
"github.com/containerd/containerd/platforms"
"github.com/containerd/continuity/fs/fstest"
"github.com/creack/pty"
"github.com/docker/buildx/localstate"
"github.com/docker/buildx/util/gitutil"
"github.com/moby/buildkit/client"
"github.com/moby/buildkit/frontend/subrequests/lint"
@ -44,6 +45,9 @@ var buildTests = []func(t *testing.T, sb integration.Sandbox){
testBuild,
testBuildStdin,
testBuildRemote,
testBuildLocalState,
testBuildLocalStateStdin,
testBuildLocalStateRemote,
testImageIDOutput,
testBuildLocalExport,
testBuildRegistryExport,
@ -122,6 +126,145 @@ COPY foo /foo
require.FileExists(t, filepath.Join(dirDest, "foo"))
}
func testBuildLocalState(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`
FROM busybox:latest AS base
COPY foo /etc/foo
RUN cp /etc/foo /etc/bar
FROM scratch
COPY --from=base /etc/bar /bar
`)
dir := tmpdir(
t,
fstest.CreateFile("build.Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)
out, err := buildCmd(sb, withDir(dir), withArgs(
"-f", "build.Dockerfile",
"--metadata-file", filepath.Join(dir, "md.json"),
".",
))
require.NoError(t, err, out)
dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
require.NoError(t, err)
type mdT struct {
BuildRef string `json:"buildx.build.ref"`
}
var md mdT
err = json.Unmarshal(dt, &md)
require.NoError(t, err)
ls, err := localstate.New(buildxConfig(sb))
require.NoError(t, err)
refParts := strings.Split(md.BuildRef, "/")
require.Len(t, refParts, 3)
ref, err := ls.ReadRef(refParts[0], refParts[1], refParts[2])
require.NoError(t, err)
require.NotNil(t, ref)
require.DirExists(t, ref.LocalPath)
require.FileExists(t, ref.DockerfilePath)
}
func testBuildLocalStateStdin(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`
FROM busybox:latest AS base
COPY foo /etc/foo
RUN cp /etc/foo /etc/bar
FROM scratch
COPY --from=base /etc/bar /bar
`)
dir := tmpdir(
t,
fstest.CreateFile("foo", []byte("foo"), 0600),
)
cmd := buildxCmd(sb, withDir(dir), withArgs("build", "--progress=quiet", "--metadata-file", filepath.Join(dir, "md.json"), "-f-", dir))
cmd.Stdin = bytes.NewReader(dockerfile)
out, err := cmd.CombinedOutput()
require.NoError(t, err, string(out))
dt, err := os.ReadFile(filepath.Join(dir, "md.json"))
require.NoError(t, err)
type mdT struct {
BuildRef string `json:"buildx.build.ref"`
}
var md mdT
err = json.Unmarshal(dt, &md)
require.NoError(t, err)
ls, err := localstate.New(buildxConfig(sb))
require.NoError(t, err)
refParts := strings.Split(md.BuildRef, "/")
require.Len(t, refParts, 3)
ref, err := ls.ReadRef(refParts[0], refParts[1], refParts[2])
require.NoError(t, err)
require.NotNil(t, ref)
require.DirExists(t, ref.LocalPath)
require.Equal(t, "-", ref.DockerfilePath)
}
func testBuildLocalStateRemote(t *testing.T, sb integration.Sandbox) {
dockerfile := []byte(`
FROM busybox:latest
COPY foo /foo
`)
dir := tmpdir(
t,
fstest.CreateFile("build.Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
)
dirDest := t.TempDir()
git, err := gitutil.New(gitutil.WithWorkingDir(dir))
require.NoError(t, err)
gitutil.GitInit(git, t)
gitutil.GitAdd(git, t, "build.Dockerfile", "foo")
gitutil.GitCommit(git, t, "initial commit")
addr := gitutil.GitServeHTTP(git, t)
out, err := buildCmd(sb, withDir(dir), withArgs(
"-f", "build.Dockerfile",
"--metadata-file", filepath.Join(dirDest, "md.json"),
"--output", "type=local,dest="+dirDest,
addr,
))
require.NoError(t, err, out)
require.FileExists(t, filepath.Join(dirDest, "foo"))
dt, err := os.ReadFile(filepath.Join(dirDest, "md.json"))
require.NoError(t, err)
type mdT struct {
BuildRef string `json:"buildx.build.ref"`
}
var md mdT
err = json.Unmarshal(dt, &md)
require.NoError(t, err)
ls, err := localstate.New(buildxConfig(sb))
require.NoError(t, err)
refParts := strings.Split(md.BuildRef, "/")
require.Len(t, refParts, 3)
ref, err := ls.ReadRef(refParts[0], refParts[1], refParts[2])
require.NoError(t, err)
require.NotNil(t, ref)
require.Equal(t, addr, ref.LocalPath)
require.Equal(t, "build.Dockerfile", ref.DockerfilePath)
}
func testBuildLocalExport(t *testing.T, sb integration.Sandbox) {
dir := createTestProject(t)
out, err := buildCmd(sb, withArgs(fmt.Sprintf("--output=type=local,dest=%s/result", dir), dir))

View File

@ -56,7 +56,7 @@ func buildxCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
if builder := sb.Address(); builder != "" {
cmd.Env = append(cmd.Env,
"BUILDX_CONFIG=/tmp/buildx-"+builder,
"BUILDX_CONFIG="+buildxConfig(sb),
"BUILDX_BUILDER="+builder,
)
}
@ -86,6 +86,13 @@ func dockerCmd(sb integration.Sandbox, opts ...cmdOpt) *exec.Cmd {
return cmd
}
func buildxConfig(sb integration.Sandbox) string {
if builder := sb.Address(); builder != "" {
return "/tmp/buildx-" + builder
}
return ""
}
func isMobyWorker(sb integration.Sandbox) bool {
name, hasFeature := driverName(sb.Name())
return name == "docker" && !hasFeature