Merge pull request #47729 from paultyng/pt/useragent

Automatic merge from submit-queue (batch tested with PRs 47286, 47729)

Set default User-Agent on http probe

**Set a default User-Agent on `httpGet` probes**:

Currently the default Go HTTP client sets a `User-Agent` specific to the language and version, but every Go client has the same one.  In Kubernetes, users can override the User-Agent by setting a header in their probe definition, but its tedious to do this everywhere.

This PR changes the default User-Agent only if not set (or removed) in the probe definition.

**Which issue this PR fixes** 
fixes #29025

**Special notes for your reviewer**:

**Release note**:

```release-note
Change default `httpGet` probe `User-Agent` to `kube-probe/<version major.minor>` if none specified, overriding the default Go `User-Agent`.
```
pull/6/head
Kubernetes Submit Queue 2017-06-28 23:14:31 -07:00 committed by GitHub
commit 343d751bc5
3 changed files with 49 additions and 11 deletions

View File

@ -14,6 +14,7 @@ go_library(
tags = ["automanaged"], tags = ["automanaged"],
deps = [ deps = [
"//pkg/probe:go_default_library", "//pkg/probe:go_default_library",
"//pkg/version:go_default_library",
"//vendor/github.com/golang/glog:go_default_library", "//vendor/github.com/golang/glog:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library", "//vendor/k8s.io/apimachinery/pkg/util/net:go_default_library",
], ],

View File

@ -26,6 +26,7 @@ import (
utilnet "k8s.io/apimachinery/pkg/util/net" utilnet "k8s.io/apimachinery/pkg/util/net"
"k8s.io/kubernetes/pkg/probe" "k8s.io/kubernetes/pkg/probe"
"k8s.io/kubernetes/pkg/version"
"github.com/golang/glog" "github.com/golang/glog"
) )
@ -68,6 +69,14 @@ func DoHTTPProbe(url *url.URL, headers http.Header, client HTTPGetInterface) (pr
// Convert errors into failures to catch timeouts. // Convert errors into failures to catch timeouts.
return probe.Failure, err.Error(), nil return probe.Failure, err.Error(), nil
} }
if _, ok := headers["User-Agent"]; !ok {
if headers == nil {
headers = http.Header{}
}
// explicitly set User-Agent so it's not set to default Go value
v := version.Get()
headers.Set("User-Agent", fmt.Sprintf("kube-probe/%s.%s", v.Major, v.Minor))
}
req.Header = headers req.Header = headers
if headers.Get("Host") != "" { if headers.Get("Host") != "" {
req.Host = headers.Get("Host") req.Host = headers.Get("Host")

View File

@ -40,12 +40,25 @@ func TestHTTPProbeChecker(t *testing.T) {
} }
} }
// Echo handler that returns the contents of request headers in the body
headerEchoHandler := func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
output := ""
for k, arr := range r.Header {
for _, v := range arr {
output += fmt.Sprintf("%s: %s\n", k, v)
}
}
w.Write([]byte(output))
}
prober := New() prober := New()
testCases := []struct { testCases := []struct {
handler func(w http.ResponseWriter, r *http.Request) handler func(w http.ResponseWriter, r *http.Request)
reqHeaders http.Header reqHeaders http.Header
health probe.Result health probe.Result
accBody string accBody string
notBody string
}{ }{
// The probe will be filled in below. This is primarily testing that an HTTP GET happens. // The probe will be filled in below. This is primarily testing that an HTTP GET happens.
{ {
@ -54,23 +67,35 @@ func TestHTTPProbeChecker(t *testing.T) {
accBody: "ok body", accBody: "ok body",
}, },
{ {
// Echo handler that returns the contents of request headers in the body handler: headerEchoHandler,
handler: func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(200)
output := ""
for k, arr := range r.Header {
for _, v := range arr {
output += fmt.Sprintf("%s: %s\n", k, v)
}
}
w.Write([]byte(output))
},
reqHeaders: http.Header{ reqHeaders: http.Header{
"X-Muffins-Or-Cupcakes": {"muffins"}, "X-Muffins-Or-Cupcakes": {"muffins"},
}, },
health: probe.Success, health: probe.Success,
accBody: "X-Muffins-Or-Cupcakes: muffins", accBody: "X-Muffins-Or-Cupcakes: muffins",
}, },
{
handler: headerEchoHandler,
reqHeaders: http.Header{
"User-Agent": {"foo/1.0"},
},
health: probe.Success,
accBody: "User-Agent: foo/1.0",
},
{
handler: headerEchoHandler,
reqHeaders: http.Header{
"User-Agent": {""},
},
health: probe.Success,
notBody: "User-Agent",
},
{
handler: headerEchoHandler,
reqHeaders: http.Header{},
health: probe.Success,
accBody: "User-Agent: kube-probe/",
},
{ {
// Echo handler that returns the contents of Host in the body // Echo handler that returns the contents of Host in the body
handler: func(w http.ResponseWriter, r *http.Request) { handler: func(w http.ResponseWriter, r *http.Request) {
@ -130,6 +155,9 @@ func TestHTTPProbeChecker(t *testing.T) {
if !strings.Contains(output, test.accBody) { if !strings.Contains(output, test.accBody) {
t.Errorf("Expected response body to contain %v, got %v", test.accBody, output) t.Errorf("Expected response body to contain %v, got %v", test.accBody, output)
} }
if test.notBody != "" && strings.Contains(output, test.notBody) {
t.Errorf("Expected response not to contain %v, got %v", test.notBody, output)
}
} }
}() }()
} }