bake: local dockerfile support for remote definition

Signed-off-by: CrazyMax <crazy-max@users.noreply.github.com>
This commit is contained in:
CrazyMax 2023-08-23 13:43:07 +02:00
parent ad674e2666
commit de9d253f45
No known key found for this signature in database
GPG Key ID: 3248E46B6BB8C7F7
4 changed files with 119 additions and 5 deletions

View File

@ -1044,6 +1044,9 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
if t.Dockerfile != nil {
dockerfilePath = *t.Dockerfile
}
if !strings.HasPrefix(dockerfilePath, "cwd://") {
dockerfilePath = path.Clean(dockerfilePath)
}
bi := build.Inputs{
ContextPath: contextPath,
@ -1054,6 +1057,20 @@ func toBuildOpt(t *Target, inp *Input) (*build.Options, error) {
bi.DockerfileInline = *t.DockerfileInline
}
updateContext(&bi, inp)
if strings.HasPrefix(bi.DockerfilePath, "cwd://") {
// If Dockerfile is local for a remote invocation, we first check if
// it's not outside the working directory and then resolve it to an
// absolute path.
bi.DockerfilePath = path.Clean(strings.TrimPrefix(bi.DockerfilePath, "cwd://"))
if err := checkPath(bi.DockerfilePath); err != nil {
return nil, err
}
var err error
bi.DockerfilePath, err = filepath.Abs(bi.DockerfilePath)
if err != nil {
return nil, err
}
}
if strings.HasPrefix(bi.ContextPath, "cwd://") {
bi.ContextPath = path.Clean(strings.TrimPrefix(bi.ContextPath, "cwd://"))
}

View File

@ -3,10 +3,12 @@ package bake
import (
"context"
"os"
"path/filepath"
"sort"
"strings"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
@ -379,7 +381,7 @@ services:
require.Equal(t, []string{"web_app"}, g["default"].Targets)
}
func TestHCLCwdPrefix(t *testing.T) {
func TestHCLContextCwdPrefix(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(
@ -400,11 +402,41 @@ func TestHCLCwdPrefix(t *testing.T) {
require.Equal(t, 1, len(m))
require.Contains(t, m, "app")
require.Equal(t, "test", *m["app"].Dockerfile)
require.Equal(t, "foo", *m["app"].Context)
assert.Equal(t, "test", *m["app"].Dockerfile)
assert.Equal(t, "foo", *m["app"].Context)
assert.Equal(t, "foo/test", bo["app"].Inputs.DockerfilePath)
assert.Equal(t, "foo", bo["app"].Inputs.ContextPath)
}
require.Equal(t, "foo/test", bo["app"].Inputs.DockerfilePath)
require.Equal(t, "foo", bo["app"].Inputs.ContextPath)
func TestHCLDockerfileCwdPrefix(t *testing.T) {
fp := File{
Name: "docker-bake.hcl",
Data: []byte(
`target "app" {
context = "."
dockerfile = "cwd://Dockerfile.app"
}`),
}
ctx := context.TODO()
cwd, err := os.Getwd()
require.NoError(t, err)
m, g, err := ReadTargets(ctx, []File{fp}, []string{"app"}, nil, nil)
require.NoError(t, err)
bo, err := TargetsToBuildOpt(m, &Input{})
require.NoError(t, err)
require.Equal(t, 1, len(g))
require.Equal(t, []string{"app"}, g["default"].Targets)
require.Equal(t, 1, len(m))
require.Contains(t, m, "app")
assert.Equal(t, "cwd://Dockerfile.app", *m["app"].Dockerfile)
assert.Equal(t, ".", *m["app"].Context)
assert.Equal(t, filepath.Join(cwd, "Dockerfile.app"), bo["app"].Inputs.DockerfilePath)
assert.Equal(t, ".", bo["app"].Inputs.ContextPath)
}
func TestOverrideMerge(t *testing.T) {

View File

@ -1332,6 +1332,10 @@ func LoadInputs(ctx context.Context, d *driver.DriverHandle, inp Inputs, pw prog
case IsRemoteURL(inp.ContextPath):
if inp.DockerfilePath == "-" {
dockerfileReader = inp.InStream
} else if filepath.IsAbs(inp.DockerfilePath) {
dockerfileDir = filepath.Dir(inp.DockerfilePath)
dockerfileName = filepath.Base(inp.DockerfilePath)
target.FrontendAttrs["dockerfilekey"] = "dockerfile"
}
target.FrontendAttrs["context"] = inp.ContextPath
default:

View File

@ -1,6 +1,7 @@
package tests
import (
"os"
"path/filepath"
"testing"
@ -25,6 +26,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
testBakeRemoteContextSubdir,
testBakeRemoteCmdContextEscapeRoot,
testBakeRemoteCmdContextEscapeRelative,
testBakeRemoteDockerfileCwd,
}
func testBakeLocal(t *testing.T, sb integration.Sandbox) {
@ -287,3 +289,62 @@ EOT
require.NoError(t, err, out)
require.FileExists(t, filepath.Join(dirDest, "foo"))
}
func testBakeRemoteDockerfileCwd(t *testing.T, sb integration.Sandbox) {
bakefile := []byte(`
target "default" {
context = "."
dockerfile = "cwd://Dockerfile.app"
}
`)
dockerfile := []byte(`
FROM scratch
COPY bar /bar
`)
dockerfileApp := []byte(`
FROM scratch
COPY foo /foo
`)
dirSpec := tmpdir(
t,
fstest.CreateFile("docker-bake.hcl", bakefile, 0600),
fstest.CreateFile("Dockerfile", dockerfile, 0600),
fstest.CreateFile("foo", []byte("foo"), 0600),
fstest.CreateFile("bar", []byte("bar"), 0600),
)
dirSrc := tmpdir(
t,
fstest.CreateFile("Dockerfile.app", dockerfileApp, 0600),
)
dirDest := t.TempDir()
git, err := gitutil.New(gitutil.WithWorkingDir(dirSpec))
require.NoError(t, err)
gitutil.GitInit(git, t)
gitutil.GitAdd(git, t, "docker-bake.hcl")
gitutil.GitAdd(git, t, "Dockerfile")
gitutil.GitAdd(git, t, "foo")
gitutil.GitAdd(git, t, "bar")
gitutil.GitCommit(git, t, "initial commit")
addr := gitutil.GitServeHTTP(git, t)
out, err := bakeCmd(
sb,
withDir(dirSrc),
withArgs(addr, "--set", "*.output=type=local,dest="+dirDest),
)
require.NoError(t, err, out)
require.FileExists(t, filepath.Join(dirDest, "foo"))
err = os.Remove(filepath.Join(dirSrc, "Dockerfile.app"))
require.NoError(t, err)
out, err = bakeCmd(
sb,
withDir(dirSrc),
withArgs(addr, "--set", "*.output=type=cacheonly"),
)
require.Error(t, err, out)
}