Skip to content

Commit

Permalink
Merge pull request #11076 from nikhiljindal/apiError
Browse files Browse the repository at this point in the history
Updating apiserver to not return 500 when a service without pods is proxied
  • Loading branch information
vishh committed Jul 24, 2015
2 parents 0a715a7 + 1517b66 commit 1a908a2
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 3 deletions.
2 changes: 1 addition & 1 deletion examples/guestbook/frontend-service.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ spec:
# type: LoadBalancer
ports:
# the port that this service should serve on
- port: 80
- port: 80
selector:
name: frontend
10 changes: 10 additions & 0 deletions pkg/api/errors/errors.go
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,16 @@ func NewBadRequest(reason string) error {
}}
}

// NewServiceUnavailable creates an error that indicates that the requested service is unavailable.
func NewServiceUnavailable(reason string) error {
return &StatusError{api.Status{
Status: api.StatusFailure,
Code: http.StatusServiceUnavailable,
Reason: api.StatusReasonServiceUnavailable,
Message: reason,
}}
}

// NewMethodNotSupported returns an error indicating the requested action is not supported on this kind.
func NewMethodNotSupported(kind, action string) error {
return &StatusError{api.Status{
Expand Down
6 changes: 6 additions & 0 deletions pkg/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1708,6 +1708,12 @@ const (
// "causes" - The original error
// Status code 500
StatusReasonInternalError = "InternalError"

// StatusReasonServiceUnavailable means that the request itself was valid,
// but the requested service is unavailable at this time.
// Retrying the request after some time might succeed.
// Status code 503
StatusReasonServiceUnavailable StatusReason = "ServiceUnavailable"
)

// StatusCause provides more information about an api.Status failure, including
Expand Down
4 changes: 2 additions & 2 deletions pkg/registry/service/rest.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ func (rs *REST) ResourceLocation(ctx api.Context, id string) (*url.URL, http.Rou
return nil, nil, err
}
if len(eps.Subsets) == 0 {
return nil, nil, fmt.Errorf("no endpoints available for %q", svcName)
return nil, nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", svcName))
}
// Pick a random Subset to start searching from.
ssSeed := rand.Intn(len(eps.Subsets))
Expand All @@ -320,7 +320,7 @@ func (rs *REST) ResourceLocation(ctx api.Context, id string) (*url.URL, http.Rou
}
}
}
return nil, nil, fmt.Errorf("no endpoints available for %q", id)
return nil, nil, errors.NewServiceUnavailable(fmt.Sprintf("no endpoints available for service %q", id))
}

// This is O(N), but we expect haystack to be small;
Expand Down
17 changes: 17 additions & 0 deletions test/integration/auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,16 @@ var aBinding string = `
}
`

var emptyEndpoints string = `
{
"kind": "Endpoints",
"apiVersion": "v1",
"metadata": {
"name": "a"%s
}
}
`

var aEndpoints string = `
{
"kind": "Endpoints",
Expand Down Expand Up @@ -243,6 +253,7 @@ var code405 = map[int]bool{405: true}
var code409 = map[int]bool{409: true}
var code422 = map[int]bool{422: true}
var code500 = map[int]bool{500: true}
var code503 = map[int]bool{503: true}

// To ensure that a POST completes before a dependent GET, set a timeout.
func addTimeoutFlag(URLString string) string {
Expand Down Expand Up @@ -299,8 +310,14 @@ func getTestRequests() []struct {
{"GET", path("services", "", ""), "", code200},
{"GET", path("services", api.NamespaceDefault, ""), "", code200},
{"POST", timeoutPath("services", api.NamespaceDefault, ""), aService, code201},
// Create an endpoint for the service (this is done automatically by endpoint controller
// whenever a service is created, but this test does not run that controller)
{"POST", timeoutPath("endpoints", api.NamespaceDefault, ""), emptyEndpoints, code201},
// Should return service unavailable when endpoint.subset is empty.
{"GET", pathWithPrefix("proxy", "services", api.NamespaceDefault, "a") + "/", "", code503},
{"PUT", timeoutPath("services", api.NamespaceDefault, "a"), aService, code200},
{"GET", path("services", api.NamespaceDefault, "a"), "", code200},
{"DELETE", timeoutPath("endpoints", api.NamespaceDefault, "a"), "", code200},
{"DELETE", timeoutPath("services", api.NamespaceDefault, "a"), "", code200},

// Normal methods on replicationControllers
Expand Down

0 comments on commit 1a908a2

Please sign in to comment.