mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-09-17 15:13:08 +00:00
Set a default user agent on all client.Client calls
Form: kube-controller-manager/v0.10.0 (linux/amd64) kubernetes/550b98e <basename(os.Argv)>/<gitVersion> (<GOOS>/<GOARCH>) kubernetes/<shortGitCommit> Can be set by other clients
This commit is contained in:
@@ -21,8 +21,10 @@ import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
gruntime "runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
@@ -68,6 +70,9 @@ type Config struct {
|
||||
// certificate. For testing only.
|
||||
Insecure bool
|
||||
|
||||
// UserAgent is an optional field that specifies the caller of this request.
|
||||
UserAgent string
|
||||
|
||||
// Transport may be used for custom HTTP behavior. This attribute may not
|
||||
// be specified with the TLS client certificate options.
|
||||
Transport http.RoundTripper
|
||||
@@ -151,6 +156,9 @@ func SetKubernetesDefaults(config *Config) error {
|
||||
if config.Prefix == "" {
|
||||
config.Prefix = "/api"
|
||||
}
|
||||
if len(config.UserAgent) == 0 {
|
||||
config.UserAgent = DefaultKubernetesUserAgent()
|
||||
}
|
||||
if len(config.Version) == 0 {
|
||||
config.Version = defaultVersionFor(config)
|
||||
}
|
||||
@@ -252,6 +260,9 @@ func HTTPWrappersForConfig(config *Config, rt http.RoundTripper) (http.RoundTrip
|
||||
case hasBasicAuth:
|
||||
rt = NewBasicAuthRoundTripper(config.Username, config.Password, rt)
|
||||
}
|
||||
if len(config.UserAgent) > 0 {
|
||||
rt = NewUserAgentRoundTripper(config.UserAgent, rt)
|
||||
}
|
||||
return rt, nil
|
||||
}
|
||||
|
||||
@@ -353,3 +364,18 @@ func defaultVersionFor(config *Config) string {
|
||||
}
|
||||
return version
|
||||
}
|
||||
|
||||
// DefaultKubernetesUserAgent returns the default user agent that clients can use.
|
||||
func DefaultKubernetesUserAgent() string {
|
||||
commit := version.Get().GitCommit
|
||||
if len(commit) > 7 {
|
||||
commit = commit[:7]
|
||||
}
|
||||
if len(commit) == 0 {
|
||||
commit = "unknown"
|
||||
}
|
||||
version := version.Get().GitVersion
|
||||
seg := strings.SplitN(version, "-", 2)
|
||||
version = seg[0]
|
||||
return fmt.Sprintf("%s/%s (%s/%s) kubernetes/%s", path.Base(os.Args[0]), version, gruntime.GOOS, gruntime.GOARCH, commit)
|
||||
}
|
||||
|
@@ -18,7 +18,11 @@ package client
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/GoogleCloudPlatform/kubernetes/pkg/api/latest"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -255,3 +259,57 @@ func TestIsConfigTransportTLS(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetKubernetesDefaults(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Config Config
|
||||
After Config
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
Config{},
|
||||
Config{
|
||||
Prefix: "/api",
|
||||
Version: latest.Version,
|
||||
Codec: latest.Codec,
|
||||
LegacyBehavior: (latest.Version == "v1beta1" || latest.Version == "v1beta2"),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
Config{
|
||||
Version: "not_an_api",
|
||||
},
|
||||
Config{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
val := &testCase.Config
|
||||
err := SetKubernetesDefaults(val)
|
||||
val.UserAgent = ""
|
||||
switch {
|
||||
case err == nil && testCase.Err:
|
||||
t.Errorf("expected error but was nil")
|
||||
continue
|
||||
case err != nil && !testCase.Err:
|
||||
t.Errorf("unexpected error %v", err)
|
||||
continue
|
||||
case err != nil:
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(*val, testCase.After) {
|
||||
t.Errorf("unexpected result object: %#v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetKubernetesDefaultsUserAgent(t *testing.T) {
|
||||
config := &Config{}
|
||||
if err := SetKubernetesDefaults(config); err != nil {
|
||||
t.Errorf("unexpected error: %v")
|
||||
}
|
||||
if !strings.Contains(config.UserAgent, "kubernetes/") {
|
||||
t.Errorf("no user agent set: %#v", config)
|
||||
}
|
||||
}
|
||||
|
@@ -65,49 +65,6 @@ func TestSetsCodec(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetDefaults(t *testing.T) {
|
||||
testCases := []struct {
|
||||
Config Config
|
||||
After Config
|
||||
Err bool
|
||||
}{
|
||||
{
|
||||
Config{},
|
||||
Config{
|
||||
Prefix: "/api",
|
||||
Version: latest.Version,
|
||||
Codec: latest.Codec,
|
||||
LegacyBehavior: (latest.Version == "v1beta1" || latest.Version == "v1beta2"),
|
||||
},
|
||||
false,
|
||||
},
|
||||
{
|
||||
Config{
|
||||
Version: "not_an_api",
|
||||
},
|
||||
Config{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
for _, testCase := range testCases {
|
||||
val := &testCase.Config
|
||||
err := SetKubernetesDefaults(val)
|
||||
switch {
|
||||
case err == nil && testCase.Err:
|
||||
t.Errorf("expected error but was nil")
|
||||
continue
|
||||
case err != nil && !testCase.Err:
|
||||
t.Errorf("unexpected error %v", err)
|
||||
continue
|
||||
case err != nil:
|
||||
continue
|
||||
}
|
||||
if !reflect.DeepEqual(*val, testCase.After) {
|
||||
t.Errorf("unexpected result object: %#v", val)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRESTClientRequires(t *testing.T) {
|
||||
if _, err := RESTClientFor(&Config{Host: "127.0.0.1", Version: "", Codec: testapi.Codec()}); err == nil {
|
||||
t.Errorf("unexpected non-error")
|
||||
|
@@ -23,6 +23,24 @@ import (
|
||||
"net/http"
|
||||
)
|
||||
|
||||
type userAgentRoundTripper struct {
|
||||
agent string
|
||||
rt http.RoundTripper
|
||||
}
|
||||
|
||||
func NewUserAgentRoundTripper(agent string, rt http.RoundTripper) http.RoundTripper {
|
||||
return &userAgentRoundTripper{agent, rt}
|
||||
}
|
||||
|
||||
func (rt *userAgentRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) {
|
||||
if len(req.Header.Get("User-Agent")) != 0 {
|
||||
return rt.rt.RoundTrip(req)
|
||||
}
|
||||
req = cloneRequest(req)
|
||||
req.Header.Set("User-Agent", rt.agent)
|
||||
return rt.rt.RoundTrip(req)
|
||||
}
|
||||
|
||||
type basicAuthRoundTripper struct {
|
||||
username string
|
||||
password string
|
||||
|
@@ -69,3 +69,33 @@ func TestBasicAuthRoundTripper(t *testing.T) {
|
||||
t.Errorf("unexpected authorization header: %#v", rt.Request)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUserAgentRoundTripper(t *testing.T) {
|
||||
rt := &testRoundTripper{}
|
||||
req := &http.Request{
|
||||
Header: make(http.Header),
|
||||
}
|
||||
req.Header.Set("User-Agent", "other")
|
||||
NewUserAgentRoundTripper("test", rt).RoundTrip(req)
|
||||
if rt.Request == nil {
|
||||
t.Fatalf("unexpected nil request: %v", rt)
|
||||
}
|
||||
if rt.Request != req {
|
||||
t.Fatalf("round tripper should not have copied request object: %#v", rt.Request)
|
||||
}
|
||||
if rt.Request.Header.Get("User-Agent") != "other" {
|
||||
t.Errorf("unexpected user agent header: %#v", rt.Request)
|
||||
}
|
||||
|
||||
req = &http.Request{}
|
||||
NewUserAgentRoundTripper("test", rt).RoundTrip(req)
|
||||
if rt.Request == nil {
|
||||
t.Fatalf("unexpected nil request: %v", rt)
|
||||
}
|
||||
if rt.Request == req {
|
||||
t.Fatalf("round tripper should have copied request object: %#v", rt.Request)
|
||||
}
|
||||
if rt.Request.Header.Get("User-Agent") != "test" {
|
||||
t.Errorf("unexpected user agent header: %#v", rt.Request)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user