Merge pull request #45684 from thaJeztah/24.0_backport_c8d_useragent_more_details
[24.0 backport] containerd: add c8d version and storage-driver to User-Agent
This commit is contained in:
commit
18278d3dc1
3 changed files with 61 additions and 22 deletions
|
@ -8,8 +8,10 @@ import (
|
|||
|
||||
"github.com/containerd/containerd/remotes"
|
||||
"github.com/containerd/containerd/remotes/docker"
|
||||
"github.com/containerd/containerd/version"
|
||||
registrytypes "github.com/docker/docker/api/types/registry"
|
||||
"github.com/docker/docker/dockerversion"
|
||||
"github.com/docker/docker/pkg/useragent"
|
||||
"github.com/docker/docker/registry"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
@ -20,7 +22,7 @@ func (i *ImageService) newResolverFromAuthConfig(ctx context.Context, authConfig
|
|||
|
||||
hosts := hostsWrapper(hostsFn, authConfig, i.registryService)
|
||||
headers := http.Header{}
|
||||
headers.Set("User-Agent", dockerversion.DockerUserAgent(ctx))
|
||||
headers.Set("User-Agent", dockerversion.DockerUserAgent(ctx, useragent.VersionInfo{Name: "containerd-client", Version: version.Version}, useragent.VersionInfo{Name: "storage-driver", Version: i.snapshotter}))
|
||||
|
||||
return docker.NewResolver(docker.ResolverOptions{
|
||||
Hosts: hosts,
|
||||
|
|
|
@ -17,12 +17,12 @@ type UAStringKey struct{}
|
|||
// In accordance with RFC 7231 (5.5.3) is of the form:
|
||||
//
|
||||
// [docker client's UA] UpstreamClient([upstream client's UA])
|
||||
func DockerUserAgent(ctx context.Context) string {
|
||||
daemonUA := getDaemonUserAgent()
|
||||
if upstreamUA := getUserAgentFromContext(ctx); len(upstreamUA) > 0 {
|
||||
return insertUpstreamUserAgent(upstreamUA, daemonUA)
|
||||
func DockerUserAgent(ctx context.Context, extraVersions ...useragent.VersionInfo) string {
|
||||
ua := useragent.AppendVersions(getDaemonUserAgent(), extraVersions...)
|
||||
if upstreamUA := getUpstreamUserAgent(ctx); upstreamUA != "" {
|
||||
ua += " " + upstreamUA
|
||||
}
|
||||
return daemonUA
|
||||
return ua
|
||||
}
|
||||
|
||||
var (
|
||||
|
@ -57,20 +57,29 @@ func getDaemonUserAgent() string {
|
|||
return daemonUA
|
||||
}
|
||||
|
||||
// getUserAgentFromContext returns the previously saved user-agent context stored in ctx, if one exists
|
||||
func getUserAgentFromContext(ctx context.Context) string {
|
||||
// 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 {
|
||||
var upstreamUA string
|
||||
if ctx != nil {
|
||||
var ki interface{} = ctx.Value(UAStringKey{})
|
||||
if ki != nil {
|
||||
if ki := ctx.Value(UAStringKey{}); ki != nil {
|
||||
upstreamUA = ctx.Value(UAStringKey{}).(string)
|
||||
}
|
||||
}
|
||||
return upstreamUA
|
||||
if upstreamUA == "" {
|
||||
return ""
|
||||
}
|
||||
return fmt.Sprintf("UpstreamClient(%s)", escapeStr(upstreamUA))
|
||||
}
|
||||
|
||||
const charsToEscape = `();\`
|
||||
|
||||
// escapeStr returns s with every rune in charsToEscape escaped by a backslash
|
||||
func escapeStr(s string, charsToEscape string) string {
|
||||
func escapeStr(s string) string {
|
||||
var ret string
|
||||
for _, currRune := range s {
|
||||
appended := false
|
||||
|
@ -87,13 +96,3 @@ func escapeStr(s string, charsToEscape string) string {
|
|||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// insertUpstreamUserAgent adds the upstream client useragent to create a user-agent
|
||||
// string of the form:
|
||||
//
|
||||
// $dockerUA UpstreamClient($upstreamUA)
|
||||
func insertUpstreamUserAgent(upstreamUA string, dockerUA string) string {
|
||||
charsToEscape := `();\`
|
||||
upstreamUAEscaped := escapeStr(upstreamUA, charsToEscape)
|
||||
return fmt.Sprintf("%s UpstreamClient(%s)", dockerUA, upstreamUAEscaped)
|
||||
}
|
||||
|
|
38
dockerversion/useragent_test.go
Normal file
38
dockerversion/useragent_test.go
Normal file
|
@ -0,0 +1,38 @@
|
|||
package dockerversion
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
|
||||
"github.com/docker/docker/pkg/useragent"
|
||||
"gotest.tools/v3/assert"
|
||||
is "gotest.tools/v3/assert/cmp"
|
||||
)
|
||||
|
||||
func TestDockerUserAgent(t *testing.T) {
|
||||
t.Run("daemon user-agent", func(t *testing.T) {
|
||||
ua := DockerUserAgent(context.TODO())
|
||||
expected := getDaemonUserAgent()
|
||||
assert.Check(t, is.Equal(ua, expected))
|
||||
})
|
||||
|
||||
t.Run("daemon user-agent custom metadata", func(t *testing.T) {
|
||||
ua := DockerUserAgent(context.TODO(), useragent.VersionInfo{Name: "hello", Version: "world"}, useragent.VersionInfo{Name: "foo", Version: "bar"})
|
||||
expected := getDaemonUserAgent() + ` hello/world foo/bar`
|
||||
assert.Check(t, is.Equal(ua, expected))
|
||||
})
|
||||
|
||||
t.Run("daemon user-agent with upstream", func(t *testing.T) {
|
||||
ctx := context.WithValue(context.TODO(), UAStringKey{}, "Magic-Client/1.2.3 (linux)")
|
||||
ua := DockerUserAgent(ctx)
|
||||
expected := getDaemonUserAgent() + ` UpstreamClient(Magic-Client/1.2.3 \(linux\))`
|
||||
assert.Check(t, is.Equal(ua, expected))
|
||||
})
|
||||
|
||||
t.Run("daemon user-agent with upstream and custom metadata", func(t *testing.T) {
|
||||
ctx := context.WithValue(context.TODO(), UAStringKey{}, "Magic-Client/1.2.3 (linux)")
|
||||
ua := DockerUserAgent(ctx, useragent.VersionInfo{Name: "hello", Version: "world"}, useragent.VersionInfo{Name: "foo", Version: "bar"})
|
||||
expected := getDaemonUserAgent() + ` hello/world foo/bar UpstreamClient(Magic-Client/1.2.3 \(linux\))`
|
||||
assert.Check(t, is.Equal(ua, expected))
|
||||
})
|
||||
}
|
Loading…
Reference in a new issue