mirror of https://github.com/docker/buildx.git
Merge pull request #3242 from rrjjvv/new-bakefile-env-var
Allow bake files to be specified via environment variable
This commit is contained in:
commit
0bed0b5653
|
|
@ -40,6 +40,11 @@ import (
|
|||
"go.opentelemetry.io/otel/attribute"
|
||||
)
|
||||
|
||||
const (
|
||||
bakeEnvFileSeparator = "BUILDX_BAKE_PATH_SEPARATOR"
|
||||
bakeEnvFilePath = "BUILDX_BAKE_FILE"
|
||||
)
|
||||
|
||||
type bakeOptions struct {
|
||||
files []string
|
||||
overrides []string
|
||||
|
|
@ -62,7 +67,7 @@ type bakeOptions struct {
|
|||
listVars bool
|
||||
}
|
||||
|
||||
func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in bakeOptions, cFlags commonFlags) (err error) {
|
||||
func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in bakeOptions, cFlags commonFlags, filesFromEnv bool) (err error) {
|
||||
mp := dockerCli.MeterProvider()
|
||||
|
||||
ctx, end, err := tracing.TraceCurrentCommand(ctx, append([]string{"bake"}, targets...),
|
||||
|
|
@ -186,7 +191,7 @@ func runBake(ctx context.Context, dockerCli command.Cli, targets []string, in ba
|
|||
return err
|
||||
}
|
||||
|
||||
files, inp, err := readBakeFiles(ctx, nodes, url, in.files, dockerCli.In(), printer)
|
||||
files, inp, err := readBakeFiles(ctx, nodes, url, in.files, dockerCli.In(), printer, filesFromEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -458,6 +463,15 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
|
|||
Aliases: []string{"f"},
|
||||
Short: "Build from a file",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
filesFromEnv := false
|
||||
if len(options.files) == 0 {
|
||||
envFiles, err := bakeEnvFiles(os.LookupEnv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
options.files = envFiles
|
||||
filesFromEnv = true
|
||||
}
|
||||
// reset to nil to avoid override is unset
|
||||
if !cmd.Flags().Lookup("no-cache").Changed {
|
||||
cFlags.noCache = nil
|
||||
|
|
@ -475,7 +489,7 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
|
|||
options.builder = rootOpts.builder
|
||||
options.metadataFile = cFlags.metadataFile
|
||||
// Other common flags (noCache, pull and progress) are processed in runBake function.
|
||||
return runBake(cmd.Context(), dockerCli, args, options, cFlags)
|
||||
return runBake(cmd.Context(), dockerCli, args, options, cFlags, filesFromEnv)
|
||||
},
|
||||
ValidArgsFunction: completion.BakeTargets(options.files),
|
||||
}
|
||||
|
|
@ -510,6 +524,37 @@ func bakeCmd(dockerCli command.Cli, rootOpts *rootOptions) *cobra.Command {
|
|||
return cmd
|
||||
}
|
||||
|
||||
func bakeEnvFiles(lookup func(string string) (string, bool)) ([]string, error) {
|
||||
sep, _ := lookup(bakeEnvFileSeparator)
|
||||
if sep == "" {
|
||||
sep = string(os.PathListSeparator)
|
||||
}
|
||||
f, ok := lookup(bakeEnvFilePath)
|
||||
if ok {
|
||||
return cleanPaths(strings.Split(f, sep))
|
||||
}
|
||||
return []string{}, nil
|
||||
}
|
||||
|
||||
func cleanPaths(p []string) ([]string, error) {
|
||||
var paths []string
|
||||
for _, f := range p {
|
||||
f = strings.TrimSpace(f)
|
||||
if f == "" {
|
||||
continue
|
||||
}
|
||||
if f == "-" {
|
||||
paths = append(paths, f)
|
||||
continue
|
||||
}
|
||||
if _, err := os.Stat(f); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
paths = append(paths, f)
|
||||
}
|
||||
return paths, nil
|
||||
}
|
||||
|
||||
func saveLocalStateGroup(dockerCli command.Cli, in bakeOptions, targets []string, bo map[string]build.Options) error {
|
||||
l, err := localstate.New(confutil.NewConfig(dockerCli))
|
||||
if err != nil {
|
||||
|
|
@ -559,7 +604,7 @@ func bakeArgs(args []string) (url, cmdContext string, targets []string) {
|
|||
return url, cmdContext, targets
|
||||
}
|
||||
|
||||
func readBakeFiles(ctx context.Context, nodes []builder.Node, url string, names []string, stdin io.Reader, pw progress.Writer) (files []bake.File, inp *bake.Input, err error) {
|
||||
func readBakeFiles(ctx context.Context, nodes []builder.Node, url string, names []string, stdin io.Reader, pw progress.Writer, filesFromEnv bool) (files []bake.File, inp *bake.Input, err error) {
|
||||
var lnames []string // local
|
||||
var rnames []string // remote
|
||||
var anames []string // both
|
||||
|
|
@ -584,7 +629,11 @@ func readBakeFiles(ctx context.Context, nodes []builder.Node, url string, names
|
|||
|
||||
if len(lnames) > 0 || url == "" {
|
||||
var lfiles []bake.File
|
||||
progress.Wrap("[internal] load local bake definitions", pw.Write, func(sub progress.SubLogger) error {
|
||||
where := ""
|
||||
if filesFromEnv {
|
||||
where = " from " + bakeEnvFilePath + " env"
|
||||
}
|
||||
progress.Wrap("[internal] load local bake definitions"+where, pw.Write, func(sub progress.SubLogger) error {
|
||||
if url != "" {
|
||||
lfiles, err = bake.ReadLocalFiles(lnames, stdin, sub)
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -143,6 +143,11 @@ Use the `-f` / `--file` option to specify the build definition file to use.
|
|||
The file can be an HCL, JSON or Compose file. If multiple files are specified,
|
||||
all are read and the build configurations are combined.
|
||||
|
||||
Alternatively, the environment variable `BUILDX_BAKE_FILE` can be used to specify the build definition to use.
|
||||
This is mutually exclusive with `-f` / `--file`; if both are specified, the environment variable is ignored.
|
||||
Multiple definitions can be specified by separating them with the system's path separator
|
||||
(typically `;` on Windows and `:` elsewhere), but can be changed with `BUILDX_BAKE_PATH_SEPARATOR`.
|
||||
|
||||
You can pass the names of the targets to build, to build only specific target(s).
|
||||
The following example builds the `db` and `webapp-release` targets that are
|
||||
defined in the `docker-bake.dev.hcl` file:
|
||||
|
|
|
|||
160
tests/bake.go
160
tests/bake.go
|
|
@ -81,6 +81,7 @@ var bakeTests = []func(t *testing.T, sb integration.Sandbox){
|
|||
testBakeMultiPlatform,
|
||||
testBakeCheckCallOutput,
|
||||
testBakeExtraHosts,
|
||||
testBakeFileFromEnvironment,
|
||||
}
|
||||
|
||||
func testBakePrint(t *testing.T, sb integration.Sandbox) {
|
||||
|
|
@ -2191,6 +2192,165 @@ target "default" {
|
|||
require.NoError(t, err, out)
|
||||
}
|
||||
|
||||
func testBakeFileFromEnvironment(t *testing.T, sb integration.Sandbox) {
|
||||
bakeFileFirst := []byte(`
|
||||
target "first" {
|
||||
dockerfile-inline = "FROM scratch\nCOPY first /"
|
||||
}
|
||||
`)
|
||||
bakeFileSecond := []byte(`
|
||||
target "second" {
|
||||
dockerfile-inline = "FROM scratch\nCOPY second /"
|
||||
}
|
||||
`)
|
||||
|
||||
t.Run("single file", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
)
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "first"),
|
||||
withEnv("BUILDX_BAKE_FILE=first.hcl"))
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(dt))
|
||||
require.Contains(t, string(dt), `#1 [internal] load local bake definitions from BUILDX_BAKE_FILE env`)
|
||||
require.Contains(t, string(dt), `#1 reading first.hcl`)
|
||||
})
|
||||
|
||||
t.Run("single file, default ignored if present", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
fstest.CreateFile("docker-bake.hcl", []byte("invalid bake file"), 0600),
|
||||
)
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "first"),
|
||||
withEnv("BUILDX_BAKE_FILE=first.hcl"))
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(dt))
|
||||
require.Contains(t, string(dt), `#1 [internal] load local bake definitions from BUILDX_BAKE_FILE env`)
|
||||
require.Contains(t, string(dt), `#1 reading first.hcl`)
|
||||
require.NotContains(t, string(dt), "docker-bake.hcl")
|
||||
})
|
||||
|
||||
t.Run("multiple files", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
fstest.CreateFile("second.hcl", bakeFileSecond, 0600),
|
||||
fstest.CreateFile("second", []byte("second"), 0600),
|
||||
)
|
||||
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "second", "first"),
|
||||
withEnv("BUILDX_BAKE_FILE=first.hcl"+string(os.PathListSeparator)+"second.hcl"))
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(dt))
|
||||
require.Contains(t, string(dt), `#1 [internal] load local bake definitions from BUILDX_BAKE_FILE env`)
|
||||
require.Contains(t, string(dt), `#1 reading first.hcl`)
|
||||
require.Contains(t, string(dt), `#1 reading second.hcl`)
|
||||
})
|
||||
|
||||
t.Run("multiple files, custom separator", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
fstest.CreateFile("second.hcl", bakeFileSecond, 0600),
|
||||
fstest.CreateFile("second", []byte("second"), 0600),
|
||||
)
|
||||
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "second", "first"),
|
||||
withEnv("BUILDX_BAKE_PATH_SEPARATOR=@", "BUILDX_BAKE_FILE=first.hcl@second.hcl"))
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(dt))
|
||||
require.Contains(t, string(dt), `#1 [internal] load local bake definitions from BUILDX_BAKE_FILE env`)
|
||||
require.Contains(t, string(dt), `#1 reading first.hcl`)
|
||||
require.Contains(t, string(dt), `#1 reading second.hcl`)
|
||||
})
|
||||
|
||||
t.Run("multiple files, one STDIN", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
fstest.CreateFile("second", []byte("second"), 0600),
|
||||
)
|
||||
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "second", "first"),
|
||||
withEnv("BUILDX_BAKE_FILE=first.hcl"+string(os.PathListSeparator)+"-"))
|
||||
w, err := cmd.StdinPipe()
|
||||
require.NoError(t, err)
|
||||
go func() {
|
||||
defer w.Close()
|
||||
w.Write(bakeFileSecond)
|
||||
}()
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.NoError(t, err, string(dt))
|
||||
require.Contains(t, string(dt), `#1 [internal] load local bake definitions from BUILDX_BAKE_FILE env`)
|
||||
require.Contains(t, string(dt), `#1 reading first.hcl`)
|
||||
require.Contains(t, string(dt), `#1 reading from stdin`)
|
||||
})
|
||||
|
||||
t.Run("env ignored if file arg passed", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
fstest.CreateFile("second.hcl", bakeFileSecond, 0600),
|
||||
)
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "-f", "first.hcl", "first", "second"),
|
||||
withEnv("BUILDX_BAKE_FILE=second.hcl"))
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.Error(t, err, string(dt))
|
||||
require.Contains(t, string(dt), "failed to find target second")
|
||||
})
|
||||
|
||||
t.Run("file does not exist", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
)
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "first"),
|
||||
withEnv("BUILDX_BAKE_FILE=wrong.hcl"))
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.Error(t, err, string(dt))
|
||||
require.Contains(t, string(dt), "wrong.hcl: no such file or directory")
|
||||
})
|
||||
|
||||
for kind, val := range map[string]string{"missing": "", "whitespace": " "} {
|
||||
t.Run(kind+" value ignored", func(t *testing.T) {
|
||||
dir := tmpdir(t,
|
||||
fstest.CreateFile("first.hcl", bakeFileFirst, 0600),
|
||||
fstest.CreateFile("first", []byte("first"), 0600),
|
||||
)
|
||||
cmd := buildxCmd(sb,
|
||||
withDir(dir),
|
||||
withArgs("bake", "--progress=plain", "first"),
|
||||
withEnv(fmt.Sprintf("BUILDX_BAKE_FILE=%s", val)))
|
||||
|
||||
dt, err := cmd.CombinedOutput()
|
||||
require.Error(t, err, string(dt))
|
||||
require.Contains(t, string(dt), "couldn't find a bake definition")
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func writeTempPrivateKey(fp string) error {
|
||||
privateKey, err := rsa.GenerateKey(rand.Reader, 2048)
|
||||
if err != nil {
|
||||
|
|
|
|||
Loading…
Reference in New Issue