2018-02-05 21:05:59 +00:00
|
|
|
package dockerversion // import "github.com/docker/docker/dockerversion"
|
2016-01-04 18:36:01 +00:00
|
|
|
|
|
|
|
import (
|
2018-04-19 22:30:59 +00:00
|
|
|
"context"
|
2016-03-09 02:18:53 +00:00
|
|
|
"fmt"
|
2016-01-04 18:36:01 +00:00
|
|
|
"runtime"
|
2023-03-22 14:32:53 +00:00
|
|
|
"sync"
|
2016-01-04 18:36:01 +00:00
|
|
|
|
|
|
|
"github.com/docker/docker/pkg/parsers/kernel"
|
|
|
|
"github.com/docker/docker/pkg/useragent"
|
|
|
|
)
|
|
|
|
|
2016-12-22 21:51:47 +00:00
|
|
|
// UAStringKey is used as key type for user-agent string in net/context struct
|
2018-08-22 02:20:22 +00:00
|
|
|
type UAStringKey struct{}
|
2016-12-22 21:51:47 +00:00
|
|
|
|
2016-01-04 18:36:01 +00:00
|
|
|
// DockerUserAgent is the User-Agent the Docker client uses to identify itself.
|
2016-03-09 02:18:53 +00:00
|
|
|
// In accordance with RFC 7231 (5.5.3) is of the form:
|
2022-07-08 16:27:07 +00:00
|
|
|
//
|
|
|
|
// [docker client's UA] UpstreamClient([upstream client's UA])
|
2023-06-01 12:09:50 +00:00
|
|
|
func DockerUserAgent(ctx context.Context, extraVersions ...useragent.VersionInfo) string {
|
|
|
|
ua := useragent.AppendVersions(getDaemonUserAgent(), extraVersions...)
|
2023-06-01 11:50:30 +00:00
|
|
|
if upstreamUA := getUpstreamUserAgent(ctx); upstreamUA != "" {
|
|
|
|
ua += " " + upstreamUA
|
2016-01-04 18:36:01 +00:00
|
|
|
}
|
2023-06-01 11:50:30 +00:00
|
|
|
return ua
|
2023-03-22 14:32:53 +00:00
|
|
|
}
|
2016-01-04 18:36:01 +00:00
|
|
|
|
2023-03-22 14:32:53 +00:00
|
|
|
var (
|
|
|
|
daemonUAOnce sync.Once
|
|
|
|
daemonUA string
|
|
|
|
)
|
|
|
|
|
2023-04-25 05:39:28 +00:00
|
|
|
// getDaemonUserAgent returns the user-agent to use for requests made by
|
2023-03-22 14:32:53 +00:00
|
|
|
// the daemon.
|
|
|
|
//
|
|
|
|
// It includes;
|
|
|
|
//
|
|
|
|
// - the docker version
|
|
|
|
// - go version
|
|
|
|
// - git-commit
|
|
|
|
// - kernel version
|
|
|
|
// - os
|
|
|
|
// - architecture
|
|
|
|
func getDaemonUserAgent() string {
|
|
|
|
daemonUAOnce.Do(func() {
|
|
|
|
httpVersion := make([]useragent.VersionInfo, 0, 6)
|
|
|
|
httpVersion = append(httpVersion, useragent.VersionInfo{Name: "docker", Version: Version})
|
|
|
|
httpVersion = append(httpVersion, useragent.VersionInfo{Name: "go", Version: runtime.Version()})
|
|
|
|
httpVersion = append(httpVersion, useragent.VersionInfo{Name: "git-commit", Version: GitCommit})
|
|
|
|
if kernelVersion, err := kernel.GetKernelVersion(); err == nil {
|
|
|
|
httpVersion = append(httpVersion, useragent.VersionInfo{Name: "kernel", Version: kernelVersion.String()})
|
|
|
|
}
|
|
|
|
httpVersion = append(httpVersion, useragent.VersionInfo{Name: "os", Version: runtime.GOOS})
|
|
|
|
httpVersion = append(httpVersion, useragent.VersionInfo{Name: "arch", Version: runtime.GOARCH})
|
|
|
|
daemonUA = useragent.AppendVersions("", httpVersion...)
|
|
|
|
})
|
|
|
|
return daemonUA
|
2016-03-09 02:18:53 +00:00
|
|
|
}
|
|
|
|
|
2023-06-01 11:50:30 +00:00
|
|
|
// getUpstreamUserAgent returns the previously saved user-agent context stored
|
|
|
|
// in ctx, if one exists, and formats it as:
|
|
|
|
//
|
|
|
|
// UpstreamClient(<upstream user agent string>)
|
|
|
|
//
|
|
|
|
// It returns an empty string if no user-agent is present in the context.
|
|
|
|
func getUpstreamUserAgent(ctx context.Context) string {
|
2016-03-09 02:18:53 +00:00
|
|
|
var upstreamUA string
|
|
|
|
if ctx != nil {
|
2023-06-01 11:50:30 +00:00
|
|
|
if ki := ctx.Value(UAStringKey{}); ki != nil {
|
2018-08-22 02:20:22 +00:00
|
|
|
upstreamUA = ctx.Value(UAStringKey{}).(string)
|
2016-03-09 02:18:53 +00:00
|
|
|
}
|
|
|
|
}
|
2023-06-01 11:50:30 +00:00
|
|
|
if upstreamUA == "" {
|
|
|
|
return ""
|
|
|
|
}
|
|
|
|
return fmt.Sprintf("UpstreamClient(%s)", escapeStr(upstreamUA))
|
2016-03-09 02:18:53 +00:00
|
|
|
}
|
|
|
|
|
2023-06-01 11:38:45 +00:00
|
|
|
const charsToEscape = `();\`
|
|
|
|
|
2016-03-09 02:18:53 +00:00
|
|
|
// escapeStr returns s with every rune in charsToEscape escaped by a backslash
|
2023-06-01 11:38:45 +00:00
|
|
|
func escapeStr(s string) string {
|
2016-03-09 02:18:53 +00:00
|
|
|
var ret string
|
|
|
|
for _, currRune := range s {
|
|
|
|
appended := false
|
2017-05-21 23:24:07 +00:00
|
|
|
for _, escapableRune := range charsToEscape {
|
|
|
|
if currRune == escapableRune {
|
2016-03-18 21:42:40 +00:00
|
|
|
ret += `\` + string(currRune)
|
2016-03-09 02:18:53 +00:00
|
|
|
appended = true
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !appended {
|
|
|
|
ret += string(currRune)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ret
|
|
|
|
}
|