Merge pull request #4574 from milas/cli-user-agent

cli/command: add WithUserAgent option
This commit is contained in:
Paweł Gronowski
2025-09-24 19:16:38 +02:00
committed by GitHub
4 changed files with 44 additions and 5 deletions
+8 -5
View File
@@ -77,6 +77,7 @@ type DockerCli struct {
dockerEndpoint docker.Endpoint
contextStoreConfig *store.Config
initTimeout time.Duration
userAgent string
res telemetryResource
// baseCtx is the base context used for internal operations. In the future
@@ -312,10 +313,10 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
if err != nil {
return nil, fmt.Errorf("unable to resolve docker endpoint: %w", err)
}
return newAPIClientFromEndpoint(endpoint, configFile)
return newAPIClientFromEndpoint(endpoint, configFile, client.WithUserAgent(UserAgent()))
}
func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigFile) (client.APIClient, error) {
func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigFile, extraOpts ...client.Opt) (client.APIClient, error) {
opts, err := ep.ClientOpts()
if err != nil {
return nil, err
@@ -330,7 +331,7 @@ func newAPIClientFromEndpoint(ep docker.Endpoint, configFile *configfile.ConfigF
if withCustomHeaders != nil {
opts = append(opts, withCustomHeaders)
}
opts = append(opts, client.WithUserAgent(UserAgent()))
opts = append(opts, extraOpts...)
return client.NewClientWithOpts(opts...)
}
@@ -551,7 +552,8 @@ func (cli *DockerCli) initialize() error {
return
}
if cli.client == nil {
if cli.client, cli.initErr = newAPIClientFromEndpoint(cli.dockerEndpoint, cli.configFile); cli.initErr != nil {
ops := []client.Opt{client.WithUserAgent(cli.userAgent)}
if cli.client, cli.initErr = newAPIClientFromEndpoint(cli.dockerEndpoint, cli.configFile, ops...); cli.initErr != nil {
return
}
}
@@ -598,6 +600,7 @@ func NewDockerCli(ops ...CLIOption) (*DockerCli, error) {
WithContentTrustFromEnv(),
WithDefaultContextStoreConfig(),
WithStandardStreams(),
WithUserAgent(UserAgent()),
}
ops = append(defaultOps, ops...)
@@ -621,7 +624,7 @@ func getServerHost(hosts []string, defaultToTLS bool) (string, error) {
}
}
// UserAgent returns the user agent string used for making API requests
// UserAgent returns the default user agent string used for making API requests.
func UserAgent() string {
return "Docker-Client/" + version.Version + " (" + runtime.GOOS + ")"
}
+12
View File
@@ -3,6 +3,7 @@ package command
import (
"context"
"encoding/csv"
"errors"
"fmt"
"io"
"net/http"
@@ -236,3 +237,14 @@ func withCustomHeadersFromEnv() (client.Opt, error) {
// see https://github.com/docker/cli/pull/5098#issuecomment-2147403871 (when updating, also update the WARNING in the function and env-var GoDoc)
return client.WithHTTPHeaders(env), nil
}
// WithUserAgent configures the User-Agent string for cli HTTP requests.
func WithUserAgent(userAgent string) CLIOption {
return func(cli *DockerCli) error {
if userAgent == "" {
return errors.New("user agent cannot be blank")
}
cli.userAgent = userAgent
return nil
}
}
+23
View File
@@ -373,3 +373,26 @@ func TestSetGoDebug(t *testing.T) {
assert.Equal(t, "val1,val2=1", os.Getenv("GODEBUG"))
})
}
func TestNewDockerCliWithCustomUserAgent(t *testing.T) {
var received string
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
received = r.UserAgent()
w.WriteHeader(http.StatusOK)
}))
defer ts.Close()
host := strings.Replace(ts.URL, "http://", "tcp://", 1)
opts := &flags.ClientOptions{Hosts: []string{host}}
cli, err := NewDockerCli(
WithUserAgent("fake-agent/0.0.1"),
)
assert.NilError(t, err)
cli.currentContext = DefaultContextName
cli.options = opts
cli.configFile = &configfile.ConfigFile{}
_, err = cli.Client().Ping(context.Background())
assert.NilError(t, err)
assert.DeepEqual(t, received, "fake-agent/0.0.1")
}
+1
View File
@@ -53,6 +53,7 @@ func newRegistryClient(dockerCLI command.Cli, allowInsecure bool) registryclient
resolver := func(ctx context.Context, index *registry.IndexInfo) registry.AuthConfig {
return command.ResolveAuthConfig(dockerCLI.ConfigFile(), index)
}
// FIXME(thaJeztah): this should use the userAgent as configured on the dockerCLI.
return registryclient.NewRegistryClient(resolver, command.UserAgent(), allowInsecure)
}