feat: add service start/stop via daemon api
This commit is contained in:
parent
01df6c4dd5
commit
d51031a875
2 changed files with 116 additions and 14 deletions
|
@ -2,28 +2,58 @@ package daemon
|
|||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
service "spud/service"
|
||||
service_definition "spud/service_definition"
|
||||
)
|
||||
|
||||
func GetApiRoutes() map[string]HandlerFuncWithContext {
|
||||
return map[string]HandlerFuncWithContext{
|
||||
"/service": ServiceList,
|
||||
"/service/": ServiceList,
|
||||
"/service/{serviceName}/": ServiceDetails,
|
||||
}
|
||||
}
|
||||
|
||||
type ServiceListPayload struct {
|
||||
Definition service_definition.ServiceDefinition `json:"definition"`
|
||||
}
|
||||
|
||||
func handleServiceListPost(w http.ResponseWriter, r *http.Request, c context.Context) {
|
||||
client := c.Value("client").(service.ServiceClient)
|
||||
var p ServiceListPayload
|
||||
json.NewDecoder(r.Body).Decode(&p)
|
||||
client.Create(p.Definition)
|
||||
w.WriteHeader(201)
|
||||
json.NewEncoder(w).Encode(p.Definition)
|
||||
}
|
||||
|
||||
func handleServiceDetailDelete(w http.ResponseWriter, r *http.Request, c context.Context) {
|
||||
client := c.Value("client").(service.ServiceClient)
|
||||
serviceName := r.PathValue("serviceName")
|
||||
client.Stop(serviceName)
|
||||
|
||||
w.WriteHeader(204)
|
||||
}
|
||||
|
||||
func handleNotImplemented(w http.ResponseWriter) {
|
||||
w.WriteHeader(501)
|
||||
}
|
||||
|
||||
func ServiceList(w http.ResponseWriter, r *http.Request, c context.Context) {
|
||||
var returnPayload []byte
|
||||
var returnCode int
|
||||
|
||||
switch r.Method {
|
||||
case "POST":
|
||||
returnPayload = []byte("Create service: Not implemented")
|
||||
returnCode = 501
|
||||
case http.MethodPost:
|
||||
handleServiceListPost(w, r, c)
|
||||
default:
|
||||
returnPayload = []byte("Not implemented")
|
||||
returnCode = 501
|
||||
handleNotImplemented(w)
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(returnCode)
|
||||
w.Write(returnPayload)
|
||||
func ServiceDetails(w http.ResponseWriter, r *http.Request, c context.Context) {
|
||||
switch r.Method {
|
||||
case http.MethodDelete:
|
||||
handleServiceDetailDelete(w, r, c)
|
||||
default:
|
||||
handleNotImplemented(w)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,48 @@ import (
|
|||
"context"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
service_definition "spud/service_definition"
|
||||
"testing"
|
||||
)
|
||||
|
||||
type MockClient struct {
|
||||
calls struct {
|
||||
Create []service_definition.ServiceDefinition
|
||||
Stop []string
|
||||
}
|
||||
}
|
||||
|
||||
func (c *MockClient) Create(s service_definition.ServiceDefinition) {
|
||||
c.calls.Create = append(c.calls.Create, s)
|
||||
}
|
||||
|
||||
func (c *MockClient) Stop(n string) {
|
||||
c.calls.Stop = append(c.calls.Stop, n)
|
||||
}
|
||||
|
||||
func TestServiceListPostCreatesService(t *testing.T) {
|
||||
mockClient := &MockClient{}
|
||||
daemonContext := context.WithValue(context.Background(), "client", mockClient)
|
||||
req := httptest.NewRequest(http.MethodPost, "/service/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
ServiceList(resp, req, daemonContext)
|
||||
|
||||
response := resp.Result()
|
||||
|
||||
if response.StatusCode != 201 {
|
||||
t.Errorf("Expected status 201, got %d", response.StatusCode)
|
||||
}
|
||||
|
||||
if len(mockClient.calls.Create) != 1 {
|
||||
t.Error("Expected a call to Create")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceListUnsupportedMethods(t *testing.T) {
|
||||
for _, method := range []string{http.MethodGet, http.MethodPut, http.MethodHead} {
|
||||
for _, method := range []string{http.MethodGet, http.MethodPut, http.MethodHead, http.MethodDelete} {
|
||||
t.Run(method, func(t *testing.T) {
|
||||
req := httptest.NewRequest(method, "/service", nil)
|
||||
req := httptest.NewRequest(method, "/service/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
ServiceList(resp, req, context.Background())
|
||||
|
@ -24,3 +59,40 @@ func TestServiceListUnsupportedMethods(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestServiceDetailsDeleteStopsService(t *testing.T) {
|
||||
mockClient := &MockClient{}
|
||||
daemonContext := context.WithValue(context.Background(), "client", mockClient)
|
||||
req := httptest.NewRequest(http.MethodDelete, "/service/service-name/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
ServiceDetails(resp, req, daemonContext)
|
||||
|
||||
response := resp.Result()
|
||||
|
||||
if response.StatusCode != 204 {
|
||||
t.Errorf("Expected status 204, got %d", response.StatusCode)
|
||||
}
|
||||
|
||||
if len(mockClient.calls.Stop) != 1 {
|
||||
t.Error("Expected a call to Stop")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceDetailUnsupportedMethods(t *testing.T) {
|
||||
for _, method := range []string{http.MethodGet, http.MethodPost, http.MethodPut, http.MethodHead} {
|
||||
t.Run(method, func(t *testing.T) {
|
||||
req := httptest.NewRequest(method, "/service/service-name/", nil)
|
||||
resp := httptest.NewRecorder()
|
||||
|
||||
ServiceDetails(resp, req, context.Background())
|
||||
|
||||
response := resp.Result()
|
||||
|
||||
if response.StatusCode != 501 {
|
||||
t.Errorf("Expected status 501, got %d.", response.StatusCode)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue