HTTP API Client: Add method to check worker state 16/182616/7
authorMaciej Wereski <m.wereski@partner.samsung.com>
Tue, 26 Jun 2018 12:50:20 +0000 (14:50 +0200)
committerMaciej Wereski <m.wereski@partner.samsung.com>
Tue, 10 Jul 2018 08:05:44 +0000 (10:05 +0200)
GetWorkerState() is convenient method for checking status of worker. It
uses HEAD HTTP method, so it's faster than calling GetWorkerInfo and
checking boruta.WorkerInfo.State. As HEAD method is used it may be
harder to debug when an issue occurs, only HTTP status code is returned.

Change-Id: Ie58934e0c520c6033f0ff28e82ea43eb675353a2
Signed-off-by: Maciej Wereski <m.wereski@partner.samsung.com>
http/client/client.go
http/client/client_test.go

index a6e2f45..55dd690 100644 (file)
@@ -145,6 +145,15 @@ func processResponse(resp *http.Response, val interface{}) error {
        }
 }
 
+// checkStatus is a helper function that returns an error when HTTP response
+// status is different than expected.
+func checkStatus(shouldBe int, resp *http.Response) (err error) {
+       if resp.StatusCode != shouldBe {
+               err = errors.New("bad HTTP status: " + resp.Status)
+       }
+       return
+}
+
 // NewRequest creates new Boruta request.
 func (client *BorutaClient) NewRequest(caps boruta.Capabilities,
        priority boruta.Priority, owner boruta.UserInfo, validAfter time.Time,
@@ -363,8 +372,21 @@ func (client *BorutaClient) GetRequestState(reqID boruta.ReqID) (boruta.ReqState
        if err != nil {
                return boruta.FAILED, err
        }
-       if resp.StatusCode != http.StatusNoContent {
-               return boruta.FAILED, errors.New("bad HTTP status: " + resp.Status)
+       if err = checkStatus(http.StatusNoContent, resp); err != nil {
+               return boruta.FAILED, err
        }
        return boruta.ReqState(resp.Header.Get("Boruta-Request-State")), nil
 }
+
+// GetWorkerState is convenient way to check state of a worker with given UUID.
+func (client *BorutaClient) GetWorkerState(uuid boruta.WorkerUUID) (boruta.WorkerState, error) {
+       path := client.url + "workers/" + string(uuid)
+       resp, err := http.Head(path)
+       if err != nil {
+               return boruta.FAIL, err
+       }
+       if err = checkStatus(http.StatusNoContent, resp); err != nil {
+               return boruta.FAIL, err
+       }
+       return boruta.WorkerState(resp.Header.Get("Boruta-Worker-State")), nil
+}
index c94ef8b..e86b0bd 100644 (file)
@@ -353,6 +353,18 @@ func TestProcessResponse(t *testing.T) {
        assert.PanicsWithValue(badType, func() { processResponse(&resp, foo) })
 }
 
+func TestCheckStatus(t *testing.T) {
+       var resp http.Response
+       resp.StatusCode = http.StatusNoContent
+       err := errors.New("bad HTTP status: 204 No Content")
+
+       assert := assert.New(t)
+
+       assert.Nil(checkStatus(http.StatusNoContent, &resp))
+       resp.Status = "204 No Content"
+       assert.Equal(err, checkStatus(http.StatusBadRequest, &resp))
+}
+
 func TestNewRequest(t *testing.T) {
        prefix := "new-req-"
        path := "/api/v1/reqs/"
@@ -1036,3 +1048,45 @@ func TestGetRequestState(t *testing.T) {
        client.url = "http://nosuchaddress.fail"
        assert.NotNil(client.GetRequestState(ReqID(1)))
 }
+
+func TestGetWorkerState(t *testing.T) {
+       prefix := "get-worker-state-"
+       path := "/api/v1/workers/"
+
+       header := make(http.Header)
+       header.Set("Boruta-Worker-State", string(RUN))
+
+       tests := []*testCase{
+               &testCase{
+                       // valid
+                       name:   prefix + "valid",
+                       path:   path + validUUID,
+                       status: http.StatusNoContent,
+                       header: header,
+               },
+               &testCase{
+                       // invalid UUID
+                       name:        prefix + "bad-uuid",
+                       path:        path + invalidID,
+                       contentType: contentJSON,
+                       status:      http.StatusBadRequest,
+               },
+       }
+
+       srv := prepareServer(http.MethodHead, tests)
+       defer srv.Close()
+       assert, client := initTest(t, srv.URL)
+
+       // valid
+       state, err := client.GetWorkerState(validUUID)
+       assert.Nil(err)
+       assert.Equal(RUN, state)
+
+       // invalid UUID
+       state, err = client.GetWorkerState(invalidID)
+       assert.Equal(errors.New("bad HTTP status: 400 Bad Request"), err)
+
+       // http.Head failure
+       client.url = "http://nosuchaddress.fail"
+       assert.NotNil(client.GetWorkerState(validUUID))
+}