Skip to content
Merged
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
13 changes: 8 additions & 5 deletions cli/command/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,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
Expand Down Expand Up @@ -313,10 +314,10 @@ func NewAPIClientFromFlags(opts *cliflags.ClientOptions, configFile *configfile.
if err != nil {
return nil, errors.Wrap(err, "unable to resolve docker endpoint")
}
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
Expand All @@ -331,7 +332,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...)
}

Expand Down Expand Up @@ -552,7 +553,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
}
}
Expand Down Expand Up @@ -599,6 +601,7 @@ func NewDockerCli(ops ...CLIOption) (*DockerCli, error) {
WithContentTrustFromEnv(),
WithDefaultContextStoreConfig(),
WithStandardStreams(),
WithUserAgent(UserAgent()),
}
ops = append(defaultOps, ops...)

Expand All @@ -622,7 +625,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 + ")"
}
Expand Down
11 changes: 11 additions & 0 deletions cli/command/cli_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,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 changes: 23 additions & 0 deletions cli/command/cli_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,3 +374,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 change: 1 addition & 0 deletions cli/command/manifest/annotate.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,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)
}

Expand Down
Loading