Skip to content

Commit 666bb24

Browse files
author
Aaron Schlesinger
committed
ref(pkg/healthsrv/healthz_handler.go): simplify the healthcheck handler
make the logic to listen on multiple channels more straightforward, and remove the logic to return health check info, as it’s not surfaced or used anywhere…
1 parent ac6e83b commit 666bb24

2 files changed

Lines changed: 33 additions & 80 deletions

File tree

pkg/healthsrv/healthz_handler.go

Lines changed: 29 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,106 +1,68 @@
11
package healthsrv
22

33
import (
4-
"encoding/json"
5-
"fmt"
4+
"log"
65
"net/http"
76
"time"
87

98
s3 "github.com/aws/aws-sdk-go/service/s3"
109
"github.com/deis/builder/pkg/sshd"
11-
"github.com/deis/pkg/log"
1210
"k8s.io/kubernetes/pkg/api"
1311
)
1412

15-
type healthZRespBucket struct {
16-
Name string `json:"name"`
17-
CreationDate time.Time `json:"creation_date"`
18-
}
19-
20-
func convertBucket(b *s3.Bucket) healthZRespBucket {
21-
return healthZRespBucket{
22-
Name: *b.Name,
23-
CreationDate: *b.CreationDate,
24-
}
25-
}
26-
27-
type healthZResp struct {
28-
Namespaces []string `json:"k8s_namespaces"`
29-
S3Buckets []healthZRespBucket `json:"s3_buckets"`
30-
SSHServerStarted bool `json:"ssh_server_started"`
31-
}
32-
33-
func marshalHealthZResp(w http.ResponseWriter, rsp healthZResp) {
34-
if err := json.NewEncoder(w).Encode(rsp); err != nil {
35-
str := fmt.Sprintf("Error encoding JSON (%s)", err)
36-
http.Error(w, str, http.StatusInternalServerError)
37-
return
38-
}
39-
}
13+
const (
14+
waitTimeout = 2 * time.Second
15+
)
4016

4117
func healthZHandler(nsLister NamespaceLister, bLister BucketLister, serverCircuit *sshd.Circuit) http.Handler {
4218
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
4319
stopCh := make(chan struct{})
4420

21+
numChecks := 0
4522
serverStateCh := make(chan struct{})
4623
serverStateErrCh := make(chan error)
4724
go circuitState(serverCircuit, serverStateCh, serverStateErrCh, stopCh)
25+
numChecks++
4826

4927
listBucketsCh := make(chan *s3.ListBucketsOutput)
5028
listBucketsErrCh := make(chan error)
5129
go listBuckets(bLister, listBucketsCh, listBucketsErrCh, stopCh)
30+
numChecks++
5231

5332
namespaceListerCh := make(chan *api.NamespaceList)
5433
namespaceListerErrCh := make(chan error)
5534
go listNamespaces(nsLister, namespaceListerCh, namespaceListerErrCh, stopCh)
35+
numChecks++
5636

57-
var rsp healthZResp
58-
serverState, bucketState, namespaceState := false, false, false
59-
for {
37+
timeoutCh := time.After(waitTimeout)
38+
defer close(stopCh)
39+
for i := 0; i < numChecks; i++ {
6040
select {
41+
// ensuring the SSH server has been started
42+
case <-serverStateCh:
6143
case err := <-serverStateErrCh:
62-
log.Err(err.Error())
63-
http.Error(w, err.Error(), http.StatusServiceUnavailable)
64-
close(stopCh)
44+
log.Printf("Healthcheck error getting server state (%s)", err)
45+
w.WriteHeader(http.StatusServiceUnavailable)
6546
return
47+
// listing S3 buckets
48+
case <-listBucketsCh:
6649
case err := <-listBucketsErrCh:
67-
str := fmt.Sprintf("Error listing buckets (%s)", err)
68-
log.Err(str)
69-
http.Error(w, str, http.StatusServiceUnavailable)
70-
close(stopCh)
50+
log.Printf("Healthcheck error listing buckets (%s)", err)
51+
w.WriteHeader(http.StatusServiceUnavailable)
7152
return
53+
// listing k8s namespaces
54+
case <-namespaceListerCh:
7255
case err := <-namespaceListerErrCh:
73-
str := fmt.Sprintf("Error listing namespaces (%s)", err)
74-
log.Err(str)
75-
http.Error(w, str, http.StatusServiceUnavailable)
76-
close(stopCh)
56+
log.Printf("Healthcheck error listing namespaces (%s)", err)
57+
w.WriteHeader(http.StatusServiceUnavailable)
58+
return
59+
// timeout for everything all of the above
60+
case <-timeoutCh:
61+
log.Printf("Healthcheck endpoint timed out after %s", waitTimeout)
62+
w.WriteHeader(http.StatusServiceUnavailable)
7763
return
78-
case <-serverStateCh:
79-
serverState = true
80-
rsp.SSHServerStarted = true
81-
if serverState && bucketState && namespaceState {
82-
marshalHealthZResp(w, rsp)
83-
return
84-
}
85-
case lbOut := <-listBucketsCh:
86-
bucketState = true
87-
for _, buck := range lbOut.Buckets {
88-
rsp.S3Buckets = append(rsp.S3Buckets, convertBucket(buck))
89-
}
90-
if serverState && bucketState && namespaceState {
91-
marshalHealthZResp(w, rsp)
92-
return
93-
}
94-
case nsList := <-namespaceListerCh:
95-
namespaceState = true
96-
for _, ns := range nsList.Items {
97-
rsp.Namespaces = append(rsp.Namespaces, ns.Name)
98-
}
99-
if serverState && bucketState && namespaceState {
100-
marshalHealthZResp(w, rsp)
101-
return
102-
}
10364
}
10465
}
66+
w.WriteHeader(http.StatusOK)
10567
})
10668
}

pkg/healthsrv/healthz_handler_test.go

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,9 @@ package healthsrv
22

33
import (
44
"bytes"
5-
"encoding/json"
65
"errors"
7-
"fmt"
86
"net/http"
97
"net/http/httptest"
10-
"strings"
118
"testing"
129

1310
"github.com/arschles/assert"
@@ -29,8 +26,7 @@ func TestHealthZCircuitOpen(t *testing.T) {
2926
assert.NoErr(t, err)
3027
h.ServeHTTP(w, r)
3128
assert.Equal(t, w.Code, http.StatusServiceUnavailable, "response code")
32-
expectedBody := "SSH Server is not yet started"
33-
assert.Equal(t, strings.TrimSpace(string(w.Body.Bytes())), expectedBody, "response body")
29+
assert.Equal(t, w.Body.Len(), 0, "response body length")
3430
}
3531

3632
func TestHealthZBucketListErr(t *testing.T) {
@@ -45,8 +41,7 @@ func TestHealthZBucketListErr(t *testing.T) {
4541
assert.NoErr(t, err)
4642
h.ServeHTTP(w, r)
4743
assert.Equal(t, w.Code, http.StatusServiceUnavailable, "response code")
48-
expectedBody := fmt.Sprintf("Error listing buckets (%s)", testErr)
49-
assert.Equal(t, strings.TrimSpace(string(w.Body.Bytes())), expectedBody, "response body")
44+
assert.Equal(t, w.Body.Len(), 0, "response body length")
5045
}
5146

5247
func TestHealthZNamespaceListErr(t *testing.T) {
@@ -61,8 +56,7 @@ func TestHealthZNamespaceListErr(t *testing.T) {
6156
assert.NoErr(t, err)
6257
h.ServeHTTP(w, r)
6358
assert.Equal(t, w.Code, http.StatusServiceUnavailable, "response code")
64-
expectedBody := fmt.Sprintf("Error listing namespaces (%s)", testErr)
65-
assert.Equal(t, strings.TrimSpace(string(w.Body.Bytes())), expectedBody, "response body")
59+
assert.Equal(t, w.Body.Len(), 0, "response body length")
6660
}
6761

6862
func TestHealthZSuccess(t *testing.T) {
@@ -77,8 +71,5 @@ func TestHealthZSuccess(t *testing.T) {
7771
assert.NoErr(t, err)
7872
h.ServeHTTP(w, r)
7973
assert.Equal(t, w.Code, http.StatusOK, "response code")
80-
expectedResp := healthZResp{Namespaces: nil, S3Buckets: nil, SSHServerStarted: true}
81-
var expectedRespBytes bytes.Buffer
82-
assert.NoErr(t, json.NewEncoder(&expectedRespBytes).Encode(expectedResp))
83-
assert.Equal(t, string(w.Body.Bytes()), string(expectedRespBytes.Bytes()), "response body")
74+
assert.Equal(t, w.Body.Len(), 0, "response body length")
8475
}

0 commit comments

Comments
 (0)