Skip to content
Open
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
74 changes: 49 additions & 25 deletions cli/command/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,23 @@ import (

const defaultInitTimeout = 2 * time.Second

// Reasons to show what determined active context
var ContextReasons = struct {
ExplicitContextFlag string
HostFlag string
HostEnv string
ContextEnv string
ConfigFile string
Default string
}{
ExplicitContextFlag: "from --context flag",
HostFlag: "from --host flag",
HostEnv: "context disabled because DOCKER_HOST environment variable is set",
ContextEnv: "DOCKER_CONTEXT environment variable set",
ConfigFile: "Current context from docker config file",
Default: "from default context",
}

// Streams is an interface which exposes the standard input and output streams
type Streams interface {
In() *streams.In
Expand All @@ -53,6 +70,7 @@ type Cli interface {
BuildKitEnabled() (bool, error)
ContextStore() store.Store
CurrentContext() string
CurrentContextReason() string
DockerEndpoint() docker.Endpoint
TelemetryClient
}
Expand All @@ -62,22 +80,23 @@ type Cli interface {
// constructor to make sure they are properly initialized with defaults
// set.
type DockerCli struct {
configFile *configfile.ConfigFile
options *cliflags.ClientOptions
in *streams.In
out *streams.Out
err *streams.Out
client client.APIClient
serverInfo ServerInfo
contentTrust bool
contextStore store.Store
currentContext string
init sync.Once
initErr error
dockerEndpoint docker.Endpoint
contextStoreConfig *store.Config
initTimeout time.Duration
res telemetryResource
configFile *configfile.ConfigFile
options *cliflags.ClientOptions
in *streams.In
out *streams.Out
err *streams.Out
client client.APIClient
serverInfo ServerInfo
contentTrust bool
contextStore store.Store
currentContext string
currentContextReason string
init sync.Once
initErr error
dockerEndpoint docker.Endpoint
contextStoreConfig *store.Config
initTimeout time.Duration
res telemetryResource

// baseCtx is the base context used for internal operations. In the future
// this may be replaced by explicitly passing a context to functions that
Expand Down Expand Up @@ -264,7 +283,7 @@ func (cli *DockerCli) Initialize(opts *cliflags.ClientOptions, ops ...CLIOption)

cli.options = opts
cli.configFile = config.LoadDefaultConfigFile(cli.err)
cli.currentContext = resolveContextName(cli.options, cli.configFile)
cli.currentContext, cli.currentContextReason = resolveContextName(cli.options, cli.configFile)
cli.contextStore = &ContextStoreWithDefault{
Store: store.New(config.ContextStoreDir(), *cli.contextStoreConfig),
Resolver: func() (*DefaultContext, error) {
Expand Down Expand Up @@ -308,7 +327,8 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
return ResolveDefaultContext(opts, storeConfig)
},
}
endpoint, err := resolveDockerEndpoint(contextStore, resolveContextName(opts, configFile))
ctxName, _ := resolveContextName(opts, configFile)
endpoint, err := resolveDockerEndpoint(contextStore, ctxName)
if err != nil {
return nil, fmt.Errorf("unable to resolve docker endpoint: %w", err)
}
Expand Down Expand Up @@ -448,30 +468,34 @@ func (cli *DockerCli) CurrentContext() string {
return cli.currentContext
}

func (cli *DockerCli) CurrentContextReason() string {
return cli.currentContextReason
}

// CurrentContext returns the current context name, based on flags,
// environment variables and the cli configuration file. It does not
// validate if the given context exists or if it's valid; errors may
// occur when trying to use it.
//
// Refer to [DockerCli.CurrentContext] above for further details.
func resolveContextName(opts *cliflags.ClientOptions, cfg *configfile.ConfigFile) string {
func resolveContextName(opts *cliflags.ClientOptions, cfg *configfile.ConfigFile) (string, string) {
if opts != nil && opts.Context != "" {
return opts.Context
return opts.Context, ContextReasons.ExplicitContextFlag
}
if opts != nil && len(opts.Hosts) > 0 {
return DefaultContextName
return DefaultContextName, ContextReasons.HostFlag
}
if os.Getenv(client.EnvOverrideHost) != "" {
return DefaultContextName
return DefaultContextName, ContextReasons.HostEnv
}
if ctxName := os.Getenv(EnvOverrideContext); ctxName != "" {
return ctxName
return ctxName, ContextReasons.ContextEnv
}
if cfg != nil && cfg.CurrentContext != "" {
// We don't validate if this context exists: errors may occur when trying to use it.
return cfg.CurrentContext
return cfg.CurrentContext, ContextReasons.ConfigFile
}
return DefaultContextName
return DefaultContextName, ContextReasons.Default
}

// DockerEndpoint returns the current docker endpoint
Expand Down
5 changes: 4 additions & 1 deletion cli/command/system/info.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ func runInfo(ctx context.Context, cmd *cobra.Command, dockerCli command.Cli, opt
if opts.format == "" {
info.UserName = dockerCli.ConfigFile().AuthConfigs[registry.IndexServer].Username
info.ClientInfo.APIVersion = dockerCli.CurrentVersion()
info.ClientInfo.Docker_Host = dockerCli.DockerEndpoint().EndpointMeta.Host
info.ClientInfo.Context_Reason = dockerCli.CurrentContextReason()
return errors.Join(prettyPrintInfo(dockerCli, info), serverConnErr)
}

Expand Down Expand Up @@ -218,8 +220,9 @@ func prettyPrintInfo(streams command.Streams, info dockerInfo) error {

func prettyPrintClientInfo(streams command.Streams, info clientInfo) {
fprintlnNonEmpty(streams.Out(), " Version: ", info.Version)
fprintln(streams.Out(), " Context: ", info.Context)
fprintln(streams.Out(), " Context:", info.Context+" ("+info.Context_Reason+")")
fprintln(streams.Out(), " Debug Mode:", info.Debug)
fprintln(streams.Out(), " Docker Host:", info.Docker_Host)

if len(info.Plugins) > 0 {
fprintln(streams.Out(), " Plugins:")
Expand Down
7 changes: 6 additions & 1 deletion cli/command/system/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ Client:{{if ne .Platform nil}}{{if ne .Platform.Name ""}} {{.Platform.Name}}{{en
Git commit: {{.GitCommit}}
Built: {{.BuildTime}}
OS/Arch: {{.Os}}/{{.Arch}}
Context: {{.Context}}
Context: {{.Context}} ({{.Context_Reason}})
Docker Host: {{.Docker_Host}}
{{- end}}

{{- if ne .Server nil}}{{with .Server}}
Expand Down Expand Up @@ -82,6 +83,8 @@ type clientVersion struct {
Arch string `json:"Arch,omitempty"`
BuildTime string `json:"BuildTime,omitempty"`
Context string `json:"Context"`
Context_Reason string `json:"Context_Reason"`
Docker_Host string `json:"Docker_Host"`
}

// newClientVersion constructs a new clientVersion. If a dockerCLI is
Expand All @@ -104,6 +107,8 @@ func newClientVersion(contextName string, dockerCli command.Cli) clientVersion {
}
if dockerCli != nil {
v.APIVersion = dockerCli.CurrentVersion()
v.Context_Reason = dockerCli.CurrentContextReason()
v.Docker_Host = dockerCli.DockerEndpoint().EndpointMeta.Host
}
return v
}
Expand Down