From 9e82074f49f21213bcb1b2bb514b6592efc15991 Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 14 Apr 2016 14:28:07 -0700 Subject: [PATCH 1/2] agent: limit HTTP check output to 4k --- command/agent/check.go | 13 +++++++------ command/agent/check_test.go | 9 +++++++++ 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/command/agent/check.go b/command/agent/check.go index ab5ae3986..cc024b7fc 100644 --- a/command/agent/check.go +++ b/command/agent/check.go @@ -2,7 +2,7 @@ package agent import ( "fmt" - "io/ioutil" + "io" "log" "net" "net/http" @@ -423,13 +423,14 @@ func (c *CheckHTTP) check() { } defer resp.Body.Close() - // Format the response body - body, err := ioutil.ReadAll(resp.Body) - if err != nil { + // Read the response into a circular buffer to limit the size + output, _ := circbuf.NewBuffer(CheckBufSize) + if _, err := io.Copy(output, resp.Body); err != nil { c.Logger.Printf("[WARN] agent: check '%v': Get error while reading body: %s", c.CheckID, err) - body = []byte{} } - result := fmt.Sprintf("HTTP GET %s: %s Output: %s", c.HTTP, resp.Status, body) + + // Format the response body + result := fmt.Sprintf("HTTP GET %s: %s Output: %s", c.HTTP, resp.Status, output.String()) if resp.StatusCode >= 200 && resp.StatusCode <= 299 { // PASSING (2xx) diff --git a/command/agent/check_test.go b/command/agent/check_test.go index 9d0a61013..053eb5148 100644 --- a/command/agent/check_test.go +++ b/command/agent/check_test.go @@ -1,6 +1,7 @@ package agent import ( + "bytes" "errors" "fmt" "log" @@ -186,7 +187,10 @@ func TestCheckTTL(t *testing.T) { func mockHTTPServer(responseCode int) *httptest.Server { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { + // Body larger than 4k limit + body := bytes.Repeat([]byte{'a'}, 2*CheckBufSize) w.WriteHeader(responseCode) + w.Write(body) return }) @@ -219,6 +223,11 @@ func expectHTTPStatus(t *testing.T, url string, status string) { if mock.state["foo"] != status { t.Fatalf("should be %v %v", status, mock.state) } + + // Allow slightly more data than CheckBufSize, for the header + if n := len(mock.output["foo"]); n > (CheckBufSize + 256) { + t.Fatalf("output too long: %d (%d-byte limit)", n, CheckBufSize) + } } func TestCheckHTTPCritical(t *testing.T) { From 1e9f3341d09f58be7abde08719995c90c7c24cdb Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Thu, 14 Apr 2016 14:31:03 -0700 Subject: [PATCH 2/2] website: mention 4K output limit for checks --- website/source/docs/agent/checks.html.markdown | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/website/source/docs/agent/checks.html.markdown b/website/source/docs/agent/checks.html.markdown index 25362bb52..b5cd2a713 100644 --- a/website/source/docs/agent/checks.html.markdown +++ b/website/source/docs/agent/checks.html.markdown @@ -20,7 +20,8 @@ There are five different kinds of checks: * Script + Interval - These checks depend on invoking an external application that performs the health check, exits with an appropriate exit code, and potentially generates some output. A script is paired with an invocation interval (e.g. - every 30 seconds). This is similar to the Nagios plugin system. + every 30 seconds). This is similar to the Nagios plugin system. The output of + a script check is limited to 4K. Output larger than this will be truncated. * HTTP + Interval - These checks make an HTTP `GET` request every Interval (e.g. every 30 seconds) to the specified URL. The status of the service depends on the HTTP response code: @@ -29,7 +30,8 @@ There are five different kinds of checks: to check a simple HTTP operation. By default, HTTP checks will be configured with a request timeout equal to the check interval, with a max of 10 seconds. It is possible to configure a custom HTTP check timeout value by specifying - the `timeout` field in the check definition. + the `timeout` field in the check definition. The output of the check is + limited to roughly 4K. Responses larger than this will be truncated. * TCP + Interval - These checks make an TCP connection attempt every Interval (e.g. every 30 seconds) to the specified IP/hostname and port. The status of @@ -68,7 +70,8 @@ determine the Docker API endpoint. The application is expected to run, perform a check of the service running inside the container, and exit with an appropriate exit code. The check should be paired with an invocation interval. The shell on which the check has to be performed is configurable which makes it possible to run containers which -have different shells on the same host. +have different shells on the same host. Check output for Docker is limited to +4K. Any output larger than this will be truncated. ## Check Definition