add list devices endpoint

This commit is contained in:
Victor Vrantchan
2016-05-16 17:37:28 -04:00
parent 4103418f55
commit 58df4a958d
6 changed files with 142 additions and 16 deletions

View File

@@ -0,0 +1,21 @@
package management
import (
"github.com/go-kit/kit/endpoint"
"golang.org/x/net/context"
)
type fetchDEPDevicesRequest struct{}
type fetchDEPDevicesResponse struct {
Err error `json:"error,omitempty"`
}
func (r fetchDEPDevicesResponse) error() error { return r.Err }
func makeFetchDevicesEndpoint(svc Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
err := svc.FetchDEPDevices()
return fetchDEPDevicesResponse{Err: err}, nil
}
}

View File

@@ -0,0 +1,37 @@
package management
import (
"encoding/json"
"net/http"
"golang.org/x/net/context"
"github.com/go-kit/kit/endpoint"
"github.com/micromdm/micromdm/device"
)
type listDevicesRequest struct{}
type listDevicesResponse struct {
devices []device.Device
Err error `json:"error,omitempty"`
}
func (r listDevicesResponse) error() error { return r.Err }
func (r listDevicesResponse) encodeList(w http.ResponseWriter) error {
jsn, err := json.MarshalIndent(r.devices, "", " ")
if err != nil {
return err
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.Write(jsn)
return nil
}
func makeListDevicesEndpoint(svc Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
ds, err := svc.Devices()
return listDevicesResponse{Err: err, devices: ds}, nil
}
}

View File

@@ -16,21 +16,6 @@ var (
errBadRouting = errors.New("inconsistent mapping between route and handler (programmer error)")
)
type fetchDEPDevicesRequest struct{}
type fetchDEPDevicesResponse struct {
Err error `json:"error,omitempty"`
}
func (r fetchDEPDevicesResponse) error() error { return r.Err }
func makeFetchDevicesEndpoint(svc Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
err := svc.FetchDEPDevices()
return fetchDEPDevicesResponse{Err: err}, nil
}
}
type addProfileRequest struct {
*workflow.Profile
}

View File

@@ -20,6 +20,9 @@ type Service interface {
// workflows
AddWorkflow(wf *workflow.Workflow) (*workflow.Workflow, error)
Workflows() ([]workflow.Workflow, error)
// Devices
Devices() ([]device.Device, error)
// dep
FetchDEPDevices() error
}
@@ -87,6 +90,11 @@ func (svc service) Workflows() ([]workflow.Workflow, error) {
return svc.workflows.Workflows()
}
// devices
func (svc service) Devices() ([]device.Device, error) {
return svc.devices.Devices()
}
// NewService creates a management service
func NewService(ds device.Datastore, ws workflow.Datastore, dc dep.Client) Service {
return &service{

View File

@@ -74,10 +74,20 @@ func ServiceHandler(ctx context.Context, svc Service, logger kitlog.Logger) http
opts...,
)
listDevicesHandler := kithttp.NewServer(
ctx,
makeListDevicesEndpoint(svc),
decodeListDevicesRequest,
encodeResponse,
opts...,
)
r := mux.NewRouter()
// dep
r.Handle("/management/v1/devices/fetch", fetchDEPHandler).Methods("POST")
//devices
r.Handle("/management/v1/devices", listDevicesHandler).Methods("GET")
// profiles
r.Handle("/management/v1/profiles", addProfileHandler).Methods("POST")
r.Handle("/management/v1/profiles", listProfilesHandler).Methods("GET")
@@ -153,6 +163,11 @@ func decodeListWorkflowsRequest(_ context.Context, r *http.Request) (interface{}
return listWorkflowsRequest{}, nil
}
// devices
func decodeListDevicesRequest(_ context.Context, r *http.Request) (interface{}, error) {
return listDevicesRequest{}, nil
}
func encodeResponse(ctx context.Context, w http.ResponseWriter, response interface{}) error {
if e, ok := response.(errorer); ok && e.error() != nil {
encodeError(ctx, e.error(), w)

View File

@@ -17,6 +17,15 @@ import (
"golang.org/x/net/context"
)
func TestListDevices(t *testing.T) {
server, svc := newServer(t)
defer teardown()
defer server.Close()
fetchDEPDevices(t, server, svc)
testListDevicesHTTP(t, svc, server, http.StatusOK)
}
func TestAddWorkflowWithProfiles(t *testing.T) {
server, svc := newServer(t)
defer teardown()
@@ -273,13 +282,47 @@ func newServer(t *testing.T) (*httptest.Server, Service) {
if err != nil {
t.Fatal(err)
}
// dep client
config := &dep.Config{
ConsumerKey: "CK_48dd68d198350f51258e885ce9a5c37ab7f98543c4a697323d75682a6c10a32501cb247e3db08105db868f73f2c972bdb6ae77112aea803b9219eb52689d42e6",
ConsumerSecret: "CS_34c7b2b531a600d99a0e4edcf4a78ded79b86ef318118c2f5bcfee1b011108c32d5302df801adbe29d446eb78f02b13144e323eb9aad51c79f01e50cb45c3a68",
AccessToken: "AT_927696831c59ba510cfe4ec1a69e5267c19881257d4bca2906a99d0785b785a6f6fdeb09774954fdd5e2d0ad952e3af52c6d8d2f21c924ba0caf4a031c158b89",
AccessSecret: "AS_c31afd7a09691d83548489336e8ff1cb11b82b6bca13f793344496a556b1f4972eaff4dde6deb5ac9cf076fdfa97ec97699c34d515947b9cf9ed31c99dded6ba",
}
svc := NewService(ds, ps, nil)
dc, err := dep.NewClient(config, dep.ServerURL("http://localhost:9000"))
if err != nil {
t.Fatal(err)
}
svc := NewService(ds, ps, dc)
handler := ServiceHandler(ctx, svc, logger)
server := httptest.NewServer(handler)
return server, svc
}
func testListDevicesHTTP(t *testing.T, svc Service, server *httptest.Server, expectedStatus int) []device.Device {
client := http.DefaultClient
theURL := server.URL + "/management/v1/devices"
resp, err := client.Get(theURL)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != expectedStatus {
io.Copy(os.Stdout, resp.Body)
t.Fatal("expected", expectedStatus, "got", resp.StatusCode)
}
// test decoding the result into a struct
var devices []device.Device
if err := json.NewDecoder(resp.Body).Decode(&devices); err != nil {
t.Log("failed to decode profiles from list response")
t.Fatal(err)
}
return devices
}
func testListWorkflowsHTTP(t *testing.T, svc Service, server *httptest.Server, expectedStatus int) []workflow.Workflow {
client := http.DefaultClient
theURL := server.URL + "/management/v1/workflows"
@@ -381,6 +424,23 @@ func TestFetchDEPDevices(t *testing.T) {
}
}
func fetchDEPDevices(t *testing.T, server *httptest.Server, svc Service) *http.Response {
client := http.DefaultClient
theURL := server.URL + "/management/v1/devices/fetch"
resp, err := client.Post(theURL, "application/json", nil)
if err != nil {
t.Fatal(err)
}
if resp.StatusCode != http.StatusOK {
io.Copy(os.Stdout, resp.Body)
t.Fatal("expected", http.StatusOK, "got", resp.StatusCode)
}
return resp
}
// a face io.ReadCloser for constructing request Body
type nopCloser struct {
io.Reader