Log useful information on 500's

* include error message in error (!!)
* add test verifying error message is correct for service ip allocation
pull/6/head
Daniel Smith 2016-08-30 16:56:56 -07:00
parent 1dfd6ab0c1
commit 1a23f5a79f
4 changed files with 66 additions and 2 deletions

View File

@ -325,7 +325,7 @@ func NewGenericServerResponse(code int, verb string, qualifiedResource unversion
default:
if code >= 500 {
reason = unversioned.StatusReasonInternalError
message = "an error on the server has prevented the request from succeeding"
message = fmt.Sprintf("an error on the server (%q) has prevented the request from succeeding", serverMessage)
}
}
switch {

View File

@ -266,7 +266,13 @@ func InstallServiceErrorHandler(s runtime.NegotiatedSerializer, container *restf
}
func serviceErrorHandler(s runtime.NegotiatedSerializer, requestResolver *RequestInfoResolver, apiVersions []string, serviceErr restful.ServiceError, request *restful.Request, response *restful.Response) {
errorNegotiated(apierrors.NewGenericServerResponse(serviceErr.Code, "", api.Resource(""), "", "", 0, false), s, unversioned.GroupVersion{}, response.ResponseWriter, request.Request)
errorNegotiated(
apierrors.NewGenericServerResponse(serviceErr.Code, "", api.Resource(""), "", serviceErr.Message, 0, false),
s,
unversioned.GroupVersion{},
response.ResponseWriter,
request.Request,
)
}
// Adds a service to return the supported api versions at the legacy /api.

View File

@ -60,6 +60,8 @@ type respLogger struct {
addedInfo string
startTime time.Time
captureErrorOutput bool
req *http.Request
w http.ResponseWriter
@ -175,6 +177,9 @@ func (rl *respLogger) Write(b []byte) (int, error) {
if !rl.statusRecorded {
rl.recordStatus(http.StatusOK) // Default if WriteHeader hasn't been called
}
if rl.captureErrorOutput {
rl.Addf("logging error output: %q\n", string(b))
}
return rl.w.Write(b)
}
@ -213,6 +218,7 @@ func (rl *respLogger) recordStatus(status int) {
stack := make([]byte, 50*1024)
stack = stack[:runtime.Stack(stack, false)]
rl.statusStack = "\n" + string(stack)
rl.captureErrorOutput = true
} else {
rl.statusStack = ""
}

View File

@ -23,6 +23,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"net"
"net/http"
"strings"
"testing"
@ -414,3 +415,54 @@ func TestMasterService(t *testing.T) {
t.Errorf("unexpected error: %v", err)
}
}
func TestServiceAlloc(t *testing.T) {
cfg := framework.NewIntegrationTestMasterConfig()
_, cidr, err := net.ParseCIDR("192.168.0.0/30")
if err != nil {
t.Fatalf("bad cidr: %v", err)
}
cfg.ServiceClusterIPRange = cidr
_, s := framework.RunAMaster(cfg)
defer s.Close()
client := client.NewOrDie(&restclient.Config{Host: s.URL, ContentConfig: restclient.ContentConfig{GroupVersion: testapi.Default.GroupVersion()}})
svc := func(i int) *api.Service {
return &api.Service{
ObjectMeta: api.ObjectMeta{
Name: fmt.Sprintf("svc-%v", i),
},
Spec: api.ServiceSpec{
Type: api.ServiceTypeClusterIP,
Ports: []api.ServicePort{
{Port: 80},
},
},
}
}
// Make a service.
if _, err := client.Services(api.NamespaceDefault).Create(svc(1)); err != nil {
t.Fatalf("got unexpected error: %v", err)
}
// Make a second service. It will fail because we're out of cluster IPs
if _, err := client.Services(api.NamespaceDefault).Create(svc(2)); err != nil {
if !strings.Contains(err.Error(), "range is full") {
t.Errorf("unexpected error text: %v", err)
}
} else {
t.Fatalf("unexpected sucess")
}
// Delete the first service.
if err := client.Services(api.NamespaceDefault).Delete(svc(1).ObjectMeta.Name); err != nil {
t.Fatalf("got unexpected error: %v", err)
}
// This time creating the second service should work.
if _, err := client.Services(api.NamespaceDefault).Create(svc(2)); err != nil {
t.Fatalf("got unexpected error: %v", err)
}
}