Skip to content

Commit

Permalink
Merge pull request #3676 from crazy-max/build-default-builder
Browse files Browse the repository at this point in the history
build: set default context builder if not specified
  • Loading branch information
cpuguy83 authored Nov 9, 2022
2 parents 4011187 + 9978469 commit 79dca7a
Show file tree
Hide file tree
Showing 5 changed files with 205 additions and 41 deletions.
13 changes: 7 additions & 6 deletions cmd/docker/aliases.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,27 @@ var allowedAliases = map[string]struct{}{
keyBuilderAlias: {},
}

func processAliases(dockerCli command.Cli, cmd *cobra.Command, args, osArgs []string) ([]string, []string, error) {
func processAliases(dockerCli command.Cli, cmd *cobra.Command, args, osArgs []string) ([]string, []string, []string, error) {
var err error
var envs []string
aliasMap := dockerCli.ConfigFile().Aliases
aliases := make([][2][]string, 0, len(aliasMap))

for k, v := range aliasMap {
if _, ok := allowedAliases[k]; !ok {
return args, osArgs, errors.Errorf("not allowed to alias %q (allowed: %#v)", k, allowedAliases)
return args, osArgs, envs, errors.Errorf("not allowed to alias %q (allowed: %#v)", k, allowedAliases)
}
if c, _, err := cmd.Find(strings.Split(v, " ")); err == nil {
if !pluginmanager.IsPluginCommand(c) {
return args, osArgs, errors.Errorf("not allowed to alias with builtin %q as target", v)
return args, osArgs, envs, errors.Errorf("not allowed to alias with builtin %q as target", v)
}
}
aliases = append(aliases, [2][]string{{k}, {v}})
}

args, osArgs, err = processBuilder(dockerCli, cmd, args, os.Args)
args, osArgs, envs, err = processBuilder(dockerCli, cmd, args, os.Args)
if err != nil {
return args, os.Args, err
return args, os.Args, envs, err
}

for _, al := range aliases {
Expand All @@ -49,5 +50,5 @@ func processAliases(dockerCli command.Cli, cmd *cobra.Command, args, osArgs []st
}
}

return args, osArgs, nil
return args, osArgs, envs, nil
}
55 changes: 46 additions & 9 deletions cmd/docker/builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package main

import (
"fmt"
"io"
"os"
"strconv"
"strings"

pluginmanager "github.com/docker/cli/cli-plugins/manager"
"github.com/docker/cli/cli/command"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
)

const (
Expand Down Expand Up @@ -40,15 +43,17 @@ func newBuilderError(warn bool, err error) error {
return fmt.Errorf("%s", errorMsg)
}

func processBuilder(dockerCli command.Cli, cmd *cobra.Command, args, osargs []string) ([]string, []string, error) {
var useLegacy, useBuilder bool
//nolint:gocyclo
func processBuilder(dockerCli command.Cli, cmd *cobra.Command, args, osargs []string) ([]string, []string, []string, error) {
var useLegacy, useBuilder, useAlias bool
var envs []string

// check DOCKER_BUILDKIT env var is present and
// if not assume we want to use the builder component
if v, ok := os.LookupEnv("DOCKER_BUILDKIT"); ok {
enabled, err := strconv.ParseBool(v)
if err != nil {
return args, osargs, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
return args, osargs, nil, errors.Wrap(err, "DOCKER_BUILDKIT environment variable expects boolean value")
}
if !enabled {
useLegacy = true
Expand All @@ -63,27 +68,28 @@ func processBuilder(dockerCli command.Cli, cmd *cobra.Command, args, osargs []st
aliasMap := dockerCli.ConfigFile().Aliases
if v, ok := aliasMap[keyBuilderAlias]; ok {
useBuilder = true
useAlias = true
builderAlias = v
}

// is this a build that should be forwarded to the builder?
fwargs, fwosargs, forwarded := forwardBuilder(builderAlias, args, osargs)
if !forwarded {
return args, osargs, nil
return args, osargs, nil, nil
}

// wcow build command must use the legacy builder
// if not opt-in through a builder component
if !useBuilder && dockerCli.ServerInfo().OSType == "windows" {
return args, osargs, nil
return args, osargs, nil, nil
}

if useLegacy {
// display warning if not wcow and continue
if dockerCli.ServerInfo().OSType != "windows" {
_, _ = fmt.Fprintln(dockerCli.Err(), newBuilderError(true, nil))
}
return args, osargs, nil
return args, osargs, nil, nil
}

// check plugin is available if cmd forwarded
Expand All @@ -94,14 +100,26 @@ func processBuilder(dockerCli command.Cli, cmd *cobra.Command, args, osargs []st
if perr != nil {
// if builder enforced with DOCKER_BUILDKIT=1, cmd must fail if plugin missing or broken
if useBuilder {
return args, osargs, newBuilderError(false, perr)
return args, osargs, nil, newBuilderError(false, perr)
}
// otherwise, display warning and continue
_, _ = fmt.Fprintln(dockerCli.Err(), newBuilderError(true, perr))
return args, osargs, nil
return args, osargs, nil, nil
}

return fwargs, fwosargs, nil
// If build subcommand is forwarded, user would expect "docker build" to
// always create a local docker image (default context builder). This is
// for better backward compatibility in case where a user could switch to
// a docker container builder with "docker buildx --use foo" which does
// not --load by default. Also makes sure that an arbitrary builder name
// is not being set in the command line or in the environment before
// setting the default context and keep "buildx install" behavior if being
// set (builder alias).
if forwarded && !useAlias && !hasBuilderName(args, os.Environ()) {
envs = append([]string{"BUILDX_BUILDER=" + dockerCli.CurrentContext()}, envs...)
}

return fwargs, fwosargs, envs, nil
}

func forwardBuilder(alias string, args, osargs []string) ([]string, []string, bool) {
Expand All @@ -127,3 +145,22 @@ func forwardBuilder(alias string, args, osargs []string) ([]string, []string, bo
}
return args, osargs, false
}

// hasBuilderName checks if a builder name is defined in args or env vars
func hasBuilderName(args []string, envs []string) bool {
var builder string
flagset := pflag.NewFlagSet("buildx", pflag.ContinueOnError)
flagset.Usage = func() {}
flagset.SetOutput(io.Discard)
flagset.StringVar(&builder, "builder", "", "")
_ = flagset.Parse(args)
if builder != "" {
return true
}
for _, e := range envs {
if strings.HasPrefix(e, "BUILDX_BUILDER=") && e != "BUILDX_BUILDER=" {
return true
}
}
return false
}
Loading

0 comments on commit 79dca7a

Please sign in to comment.