diff --git a/discovery/marathon/marathon.go b/discovery/marathon/marathon.go index 452ae9389..dc23dca00 100644 --- a/discovery/marathon/marathon.go +++ b/discovery/marathon/marathon.go @@ -336,6 +336,10 @@ func fetchApps(client *http.Client, url string) (*AppList, error) { return nil, err } + if (resp.StatusCode < 200) || (resp.StatusCode >= 300) { + return nil, fmt.Errorf("Non 2xx status '%v' response during marathon service discovery", resp.StatusCode) + } + body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err diff --git a/discovery/marathon/marathon_test.go b/discovery/marathon/marathon_test.go index 6b7c6f315..5ad978e58 100644 --- a/discovery/marathon/marathon_test.go +++ b/discovery/marathon/marathon_test.go @@ -16,7 +16,9 @@ package marathon import ( "context" "errors" + "io" "net/http" + "net/http/httptest" "testing" "time" @@ -326,6 +328,33 @@ func TestMarathonZeroTaskPorts(t *testing.T) { } } +func Test500ErrorHttpResponseWithValidJSONBody(t *testing.T) { + var ( + ch = make(chan []*targetgroup.Group, 1) + client = fetchApps + ) + // Simulate 500 error with a valid JSON response. + respHandler := func(w http.ResponseWriter, r *http.Request) { + w.WriteHeader(http.StatusInternalServerError) + w.Header().Set("Content-Type", "application/json") + io.WriteString(w, `{}`) + } + // Create a test server with mock HTTP handler. + ts := httptest.NewServer(http.HandlerFunc(respHandler)) + defer ts.Close() + // Backup conf for future tests. + backupConf := conf + defer func() { + conf = backupConf + }() + // Setup conf for the test case. + conf = SDConfig{Servers: []string{ts.URL}} + // Execute test case and validate behaviour. + if err := testUpdateServices(client, ch); err == nil { + t.Fatalf("Expected error for 5xx HTTP response from marathon server") + } +} + func marathonTestAppListWithoutPortMappings(labels map[string]string, runningTasks int) *AppList { var ( task = Task{