Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 17 additions & 14 deletions cli/command/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"path/filepath"
"runtime"
"strconv"
"sync"

"github.com/docker/cli/cli/config"
cliconfig "github.com/docker/cli/cli/config"
Expand Down Expand Up @@ -71,19 +72,20 @@ type Cli interface {
// DockerCli is an instance the docker command line client.
// Instances of the client can be returned from NewDockerCli.
type DockerCli struct {
configFile *configfile.ConfigFile
in *streams.In
out *streams.Out
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
contentTrust bool
newContainerizeClient func(string) (clitypes.ContainerizedClient, error)
contextStore store.Store
currentContext string
dockerEndpoint docker.Endpoint
contextStoreConfig store.Config
configFile *configfile.ConfigFile
in *streams.In
out *streams.Out
err io.Writer
client client.APIClient
serverInfo ServerInfo
clientInfo ClientInfo
contentTrust bool
newContainerizeClient func(string) (clitypes.ContainerizedClient, error)
contextStore store.Store
currentContext string
dockerEndpoint docker.Endpoint
contextStoreConfig store.Config
initializeFromClientOnce sync.Once
}

// DefaultVersion returns api.defaultVersion or DOCKER_API_VERSION if specified.
Expand All @@ -93,6 +95,7 @@ func (cli *DockerCli) DefaultVersion() string {

// Client returns the APIClient
func (cli *DockerCli) Client() client.APIClient {
cli.initializeFromClientOnce.Do(cli.initializeFromClient)
return cli.client
}

Expand Down Expand Up @@ -133,6 +136,7 @@ func (cli *DockerCli) ConfigFile() *configfile.ConfigFile {
// ServerInfo returns the server version details for the host this client is
// connected to
func (cli *DockerCli) ServerInfo() ServerInfo {
cli.initializeFromClientOnce.Do(cli.initializeFromClient)
return cli.serverInfo
}

Expand Down Expand Up @@ -253,7 +257,6 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...Initialize
DefaultVersion: cli.client.ClientVersion(),
HasExperimental: hasExperimental,
}
cli.initializeFromClient()
return nil
}

Expand Down
51 changes: 51 additions & 0 deletions cli/command/commands/lazychecks/lazychecks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package lazychecks

import (
"errors"
"fmt"
"strconv"
"strings"

"github.com/docker/cli/cli/command"
"github.com/spf13/pflag"
)

var lazyChecks []LazyCheck

const lazyCheckAnnotation = "lazy-checks"

// LazyCheck is a callback that is called lazily to know if a command / flag should be enabled
type LazyCheck func(clientInfo command.ClientInfo, serverInfo command.ServerInfo, clientVersion string) error

// AddLazyFlagCheck adds a LazyCheck on a flag
func AddLazyFlagCheck(flagset *pflag.FlagSet, name string, check LazyCheck) {
index := len(lazyChecks)
lazyChecks = append(lazyChecks, check)
f := flagset.Lookup(name)
if f == nil {
return
}
if f.Annotations == nil {
f.Annotations = map[string][]string{}
}
f.Annotations[lazyCheckAnnotation] = append(f.Annotations[lazyCheckAnnotation], fmt.Sprintf("%d", index))
}

// EvaluateFlagLazyChacks evaluates the lazy checks associated with a flag depending on client/server info
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// EvaluateFlagLazyChacks evaluates the lazy checks associated with a flag depending on client/server info
// EvaluateFlagLazyChecks evaluates the lazy checks associated with a flag depending on client/server info

func EvaluateFlagLazyChacks(flag *pflag.Flag, clientInfo command.ClientInfo, serverInfo command.ServerInfo, clientVersion string) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
func EvaluateFlagLazyChacks(flag *pflag.Flag, clientInfo command.ClientInfo, serverInfo command.ServerInfo, clientVersion string) error {
func EvaluateFlagLazyChecks(flag *pflag.Flag, clientInfo command.ClientInfo, serverInfo command.ServerInfo, clientVersion string) error {

var errs []string
for _, indexStr := range flag.Annotations[lazyCheckAnnotation] {
index, err := strconv.ParseInt(indexStr, 10, 32)
if err != nil {
errs = append(errs, err.Error())
continue
}
if err := lazyChecks[int(index)](clientInfo, serverInfo, clientVersion); err != nil {
errs = append(errs, err.Error())
}
}
if len(errs) == 0 {
return nil
}
return errors.New(strings.Join(errs, "\n"))
}
9 changes: 5 additions & 4 deletions cli/command/context/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
// NewContextCommand returns the context cli subcommand
func NewContextCommand(dockerCli command.Cli) *cobra.Command {
cmd := &cobra.Command{
Use: "context",
Short: "Manage contexts",
Args: cli.NoArgs,
RunE: command.ShowHelp(dockerCli.Err()),
Use: "context",
Short: "Manage contexts",
Args: cli.NoArgs,
RunE: command.ShowHelp(dockerCli.Err()),
Annotations: map[string]string{"local-only": ""},
}
cmd.AddCommand(
newCreateCommand(dockerCli),
Expand Down
22 changes: 15 additions & 7 deletions cli/command/image/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ import (

"github.com/docker/cli/cli"
"github.com/docker/cli/cli/command"
"github.com/docker/cli/cli/command/commands/lazychecks"
"github.com/docker/cli/cli/command/image/build"
"github.com/docker/cli/opts"
"github.com/docker/distribution/reference"
"github.com/docker/docker/api"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/versions"
"github.com/docker/docker/pkg/archive"
"github.com/docker/docker/pkg/idtools"
"github.com/docker/docker/pkg/jsonmessage"
Expand Down Expand Up @@ -151,13 +153,19 @@ func NewBuildCommand(dockerCli command.Cli) *cobra.Command {

flags.StringVar(&options.platform, "platform", os.Getenv("DOCKER_DEFAULT_PLATFORM"), "Set platform if server is multi-platform capable")
// Platform is not experimental when BuildKit is used
buildkitEnabled, err := command.BuildKitEnabled(dockerCli.ServerInfo())
if err == nil && buildkitEnabled {
flags.SetAnnotation("platform", "version", []string{"1.38"})
} else {
flags.SetAnnotation("platform", "version", []string{"1.32"})
flags.SetAnnotation("platform", "experimental", nil)
}
lazychecks.AddLazyFlagCheck(flags, "platform", func(ci command.ClientInfo, si command.ServerInfo, clientVersion string) error {
buildkitEnabled, err := command.BuildKitEnabled(si)
if err == nil && buildkitEnabled {
if versions.LessThan(clientVersion, "1.38") {
return fmt.Errorf("with buildkit enabled, --platform flag requires API version 1.38 or greater (current is %s)", clientVersion)
}
} else {
if versions.LessThan(clientVersion, "1.32") || !si.HasExperimental {
return fmt.Errorf("with buildkit disabled, --platform requires a daemon with API version 1.32 or greater and experimental enabled")
}
}
return nil
})

flags.BoolVar(&options.squash, "squash", false, "Squash newly built layers into a single new layer")
flags.SetAnnotation("squash", "experimental", nil)
Expand Down
Loading