mirror of
https://github.com/micromdm/micromdm/
synced 2026-08-08 18:55:34 +08:00
refactor blueprint service for HA (#348)
Cleanup blueprints by moving the service into its own package. Closes #297
This commit is contained in:
@@ -148,7 +148,7 @@ func (cmd *applyCommand) applyBlueprint(args []string) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err = cmd.applysvc.ApplyBlueprint(ctx, &blpt)
|
||||
err = cmd.blueprintsvc.ApplyBlueprint(ctx, &blpt)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/micromdm/micromdm/pkg/crypto"
|
||||
"github.com/micromdm/micromdm/platform/api/server/list"
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/profile"
|
||||
)
|
||||
|
||||
@@ -232,7 +233,7 @@ func (cmd *getCommand) getBlueprints(args []string) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
blueprints, err := cmd.list.GetBlueprints(ctx, list.GetBlueprintsOption{FilterName: *flBlueprintName})
|
||||
blueprints, err := cmd.blueprintsvc.GetBlueprints(ctx, blueprint.GetBlueprintsOption{FilterName: *flBlueprintName})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
BIN
cmd/mdmctl/mdmctl
Executable file
BIN
cmd/mdmctl/mdmctl
Executable file
Binary file not shown.
@@ -18,7 +18,7 @@ func (cmd *removeCommand) removeBlueprints(args []string) error {
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
err := cmd.remove.RemoveBlueprints(ctx, strings.Split(*flBlueprintName, ","))
|
||||
err := cmd.blueprintsvc.RemoveBlueprints(ctx, strings.Split(*flBlueprintName, ","))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -7,14 +7,16 @@ import (
|
||||
"github.com/micromdm/micromdm/platform/api/server/apply"
|
||||
"github.com/micromdm/micromdm/platform/api/server/list"
|
||||
"github.com/micromdm/micromdm/platform/api/server/remove"
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/profile"
|
||||
)
|
||||
|
||||
type remoteServices struct {
|
||||
profilesvc profile.Service
|
||||
applysvc apply.Service
|
||||
list list.Service
|
||||
remove remove.Service
|
||||
profilesvc profile.Service
|
||||
blueprintsvc blueprint.Service
|
||||
applysvc apply.Service
|
||||
list list.Service
|
||||
remove remove.Service
|
||||
}
|
||||
|
||||
func setupClient(logger log.Logger) (*remoteServices, error) {
|
||||
@@ -22,20 +24,28 @@ func setupClient(logger log.Logger) (*remoteServices, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
applysvc, err := apply.NewClient(
|
||||
cfg.ServerURL, logger, cfg.APIToken,
|
||||
|
||||
profilesvc, err := profile.NewHTTPClient(
|
||||
cfg.ServerURL, cfg.APIToken, logger,
|
||||
httptransport.SetClient(skipVerifyHTTPClient(cfg.SkipVerify)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
profilesvc, err := profile.NewHTTPClient(
|
||||
blueprintsvc, err := blueprint.NewHTTPClient(
|
||||
cfg.ServerURL, cfg.APIToken, logger,
|
||||
httptransport.SetClient(skipVerifyHTTPClient(cfg.SkipVerify)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
applysvc, err := apply.NewClient(
|
||||
cfg.ServerURL, logger, cfg.APIToken,
|
||||
httptransport.SetClient(skipVerifyHTTPClient(cfg.SkipVerify)))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
listsvc, err := list.NewClient(
|
||||
cfg.ServerURL, logger, cfg.APIToken,
|
||||
httptransport.SetClient(skipVerifyHTTPClient(cfg.SkipVerify)))
|
||||
@@ -51,9 +61,10 @@ func setupClient(logger log.Logger) (*remoteServices, error) {
|
||||
}
|
||||
|
||||
return &remoteServices{
|
||||
profilesvc: profilesvc,
|
||||
applysvc: applysvc,
|
||||
list: listsvc,
|
||||
remove: rmsvc,
|
||||
profilesvc: profilesvc,
|
||||
blueprintsvc: blueprintsvc,
|
||||
applysvc: applysvc,
|
||||
list: listsvc,
|
||||
remove: rmsvc,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ import (
|
||||
"github.com/micromdm/micromdm/platform/apns"
|
||||
"github.com/micromdm/micromdm/platform/appstore"
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
blueprintbuiltin "github.com/micromdm/micromdm/platform/blueprint/builtin"
|
||||
"github.com/micromdm/micromdm/platform/command"
|
||||
"github.com/micromdm/micromdm/platform/config"
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
@@ -186,7 +187,7 @@ func serve(args []string) error {
|
||||
stdlog.Fatalf("enrollment service: %s", sm.err)
|
||||
}
|
||||
|
||||
bpDB, err := blueprint.NewDB(sm.db, sm.profileDB, userDB)
|
||||
bpDB, err := blueprintbuiltin.NewDB(sm.db, sm.profileDB, userDB)
|
||||
if err != nil {
|
||||
stdlog.Fatal(err)
|
||||
}
|
||||
@@ -277,15 +278,21 @@ func serve(args []string) error {
|
||||
|
||||
profileEndpoints := profile.MakeServerEndpoints(profilesvc)
|
||||
|
||||
var blueprintsvc blueprint.Service
|
||||
{
|
||||
blueprintsvc = blueprint.New(bpDB)
|
||||
}
|
||||
|
||||
blueprintEndpoints := blueprint.MakeServerEndpoints(blueprintsvc)
|
||||
|
||||
var listsvc list.Service
|
||||
{
|
||||
l := &list.ListService{
|
||||
DEPClient: dc,
|
||||
Devices: devDB,
|
||||
Tokens: tokenDB,
|
||||
Blueprints: bpDB,
|
||||
Apps: appDB,
|
||||
Users: userDB,
|
||||
DEPClient: dc,
|
||||
Devices: devDB,
|
||||
Tokens: tokenDB,
|
||||
Apps: appDB,
|
||||
Users: userDB,
|
||||
}
|
||||
listsvc = l
|
||||
|
||||
@@ -301,7 +308,6 @@ func serve(args []string) error {
|
||||
listEndpoints := list.Endpoints{
|
||||
ListDevicesEndpoint: listDevicesEndpoint,
|
||||
GetDEPTokensEndpoint: list.MakeGetDEPTokensEndpoint(listsvc),
|
||||
GetBlueprintsEndpoint: list.MakeGetBlueprintsEndpoint(listsvc),
|
||||
GetDEPAccountInfoEndpoint: list.MakeGetDEPAccountInfoEndpoint(listsvc),
|
||||
GetDEPProfileEndpoint: list.MakeGetDEPProfileEndpoint(listsvc),
|
||||
GetDEPDeviceEndpoint: list.MakeGetDEPDeviceDetailsEndpoint(listsvc),
|
||||
@@ -313,7 +319,6 @@ func serve(args []string) error {
|
||||
{
|
||||
l := &apply.ApplyService{
|
||||
DEPClient: dc,
|
||||
Blueprints: bpDB,
|
||||
Tokens: tokenDB,
|
||||
Apps: appDB,
|
||||
Users: userDB,
|
||||
@@ -325,11 +330,6 @@ func serve(args []string) error {
|
||||
}
|
||||
}
|
||||
|
||||
var applyBlueprintEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyBlueprintEndpoint = apply.MakeApplyBlueprintEndpoint(applysvc)
|
||||
}
|
||||
|
||||
var defineDEPProfileEndpoint endpoint.Endpoint
|
||||
{
|
||||
defineDEPProfileEndpoint = apply.MakeDefineDEPProfile(applysvc)
|
||||
@@ -346,7 +346,6 @@ func serve(args []string) error {
|
||||
}
|
||||
|
||||
applyEndpoints := apply.Endpoints{
|
||||
ApplyBlueprintEndpoint: applyBlueprintEndpoint,
|
||||
ApplyDEPTokensEndpoint: apply.MakeApplyDEPTokensEndpoint(applysvc),
|
||||
DefineDEPProfileEndpoint: defineDEPProfileEndpoint,
|
||||
AppUploadEndpoint: appUploadEndpoint,
|
||||
@@ -358,7 +357,7 @@ func serve(args []string) error {
|
||||
|
||||
listAPIHandlers := list.MakeHTTPHandlers(ctx, listEndpoints, connectOpts...)
|
||||
|
||||
rmsvc := &remove.RemoveService{Blueprints: bpDB, RemoveService: removeService}
|
||||
rmsvc := &remove.RemoveService{RemoveService: removeService}
|
||||
removeAPIHandlers := remove.MakeHTTPHandlers(ctx, remove.MakeEndpoints(rmsvc), connectOpts...)
|
||||
|
||||
connectHandlers := connect.MakeHTTPHandlers(ctx, connectEndpoints, connectOpts...)
|
||||
@@ -378,10 +377,12 @@ func serve(args []string) error {
|
||||
})
|
||||
|
||||
profilesHandler := profile.MakeHTTPHandler(profileEndpoints, logger)
|
||||
blueprintsHandler := blueprint.MakeHTTPHandler(blueprintEndpoints, logger)
|
||||
|
||||
// API commands. Only handled if the user provides an api key.
|
||||
if *flAPIKey != "" {
|
||||
r.Handle("/v1/profiles", apiAuthMiddleware(*flAPIKey, profilesHandler))
|
||||
r.Handle("/v1/blueprints", apiAuthMiddleware(*flAPIKey, blueprintsHandler))
|
||||
r.Handle("/push/{udid}", apiAuthMiddleware(*flAPIKey, pushHandlers.PushHandler))
|
||||
r.Handle("/v1/commands", apiAuthMiddleware(*flAPIKey, commandHandlers.NewCommandHandler)).Methods("POST")
|
||||
r.Handle("/v1/devices", apiAuthMiddleware(*flAPIKey, listAPIHandlers.ListDevicesHandler)).Methods("GET")
|
||||
@@ -389,9 +390,6 @@ func serve(args []string) error {
|
||||
r.Handle("/v1/devices/{udid}/unblock", apiAuthMiddleware(*flAPIKey, removeAPIHandlers.UnblockDeviceHandler)).Methods("POST")
|
||||
r.Handle("/v1/dep-tokens", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPTokensHandler)).Methods("GET")
|
||||
r.Handle("/v1/dep-tokens", apiAuthMiddleware(*flAPIKey, applyAPIHandlers.DEPTokensHandler)).Methods("PUT")
|
||||
r.Handle("/v1/blueprints", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetBlueprintsHandler)).Methods("GET")
|
||||
r.Handle("/v1/blueprints", apiAuthMiddleware(*flAPIKey, applyAPIHandlers.BlueprintHandler)).Methods("PUT")
|
||||
r.Handle("/v1/blueprints", apiAuthMiddleware(*flAPIKey, removeAPIHandlers.BlueprintHandler)).Methods("DELETE")
|
||||
r.Handle("/v1/dep/devices", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPDeviceDetailsHandler)).Methods("GET")
|
||||
r.Handle("/v1/dep/account", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPAccountInfoHandler)).Methods("GET")
|
||||
r.Handle("/v1/dep/profiles", apiAuthMiddleware(*flAPIKey, listAPIHandlers.GetDEPProfileHandler)).Methods("GET")
|
||||
|
||||
@@ -16,16 +16,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var applyBlueprintEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyBlueprintEndpoint = httptransport.NewClient(
|
||||
"PUT",
|
||||
copyURL(u, "/v1/blueprints"),
|
||||
encodeRequestWithToken(token, EncodeHTTPGenericRequest),
|
||||
DecodeBlueprintResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
var applyDEPTokensEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyDEPTokensEndpoint = httptransport.NewClient(
|
||||
@@ -82,7 +72,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
}
|
||||
|
||||
return Endpoints{
|
||||
ApplyBlueprintEndpoint: applyBlueprintEndpoint,
|
||||
ApplyDEPTokensEndpoint: applyDEPTokensEndpoint,
|
||||
DefineDEPProfileEndpoint: defineDEPProfileEndpoint,
|
||||
AppUploadEndpoint: uploadAppEndpoint,
|
||||
|
||||
@@ -7,12 +7,10 @@ import (
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/micromdm/dep"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
|
||||
type Endpoints struct {
|
||||
ApplyBlueprintEndpoint endpoint.Endpoint
|
||||
ApplyDEPTokensEndpoint endpoint.Endpoint
|
||||
DefineDEPProfileEndpoint endpoint.Endpoint
|
||||
AppUploadEndpoint endpoint.Endpoint
|
||||
@@ -67,15 +65,6 @@ func (e Endpoints) DefineDEPProfile(ctx context.Context, p *dep.Profile) (*dep.P
|
||||
return response.ProfileResponse, response.Err
|
||||
}
|
||||
|
||||
func (e Endpoints) ApplyBlueprint(ctx context.Context, bp *blueprint.Blueprint) error {
|
||||
request := blueprintRequest{Blueprint: bp}
|
||||
resp, err := e.ApplyBlueprintEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return resp.(blueprintResponse).Err
|
||||
}
|
||||
|
||||
func (e Endpoints) ApplyDEPToken(ctx context.Context, P7MContent []byte) error {
|
||||
req := depTokensRequest{P7MContent: P7MContent}
|
||||
resp, err := e.ApplyDEPTokensEndpoint(ctx, req)
|
||||
@@ -85,16 +74,6 @@ func (e Endpoints) ApplyDEPToken(ctx context.Context, P7MContent []byte) error {
|
||||
return resp.(depTokensResponse).Err
|
||||
}
|
||||
|
||||
func MakeApplyBlueprintEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(blueprintRequest)
|
||||
err = svc.ApplyBlueprint(ctx, req.Blueprint)
|
||||
return blueprintResponse{
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func MakeApplyDEPTokensEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(depTokensRequest)
|
||||
@@ -161,16 +140,6 @@ type appUploadResponse struct {
|
||||
|
||||
func (r appUploadResponse) error() error { return r.Err }
|
||||
|
||||
type blueprintRequest struct {
|
||||
Blueprint *blueprint.Blueprint `json:"blueprint"`
|
||||
}
|
||||
|
||||
type blueprintResponse struct {
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r blueprintResponse) error() error { return r.Err }
|
||||
|
||||
type depTokensRequest struct {
|
||||
P7MContent []byte `json:"p7m_content"`
|
||||
}
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/appstore"
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
"github.com/micromdm/micromdm/platform/pubsub"
|
||||
"github.com/micromdm/micromdm/platform/remove"
|
||||
@@ -25,7 +24,6 @@ import (
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
ApplyBlueprint(ctx context.Context, bp *blueprint.Blueprint) error
|
||||
ApplyDEPToken(ctx context.Context, P7MContent []byte) error
|
||||
UploadApp(ctx context.Context, manifestName string, manifest io.Reader, pkgName string, pkg io.Reader) error
|
||||
ApplyUser(ctx context.Context, u user.User) (*user.User, error)
|
||||
@@ -37,10 +35,9 @@ type ApplyService struct {
|
||||
mtx sync.RWMutex
|
||||
DEPClient dep.Client
|
||||
|
||||
Blueprints *blueprint.DB
|
||||
Tokens *deptoken.DB
|
||||
Apps appstore.AppStore
|
||||
Users *user.DB
|
||||
Tokens *deptoken.DB
|
||||
Apps appstore.AppStore
|
||||
Users *user.DB
|
||||
*remove.RemoveService
|
||||
}
|
||||
|
||||
@@ -105,10 +102,6 @@ func (svc *ApplyService) WatchTokenUpdates(pubsub pubsub.Subscriber) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (svc *ApplyService) ApplyBlueprint(ctx context.Context, bp *blueprint.Blueprint) error {
|
||||
return svc.Blueprints.Save(bp)
|
||||
}
|
||||
|
||||
// unwrapSMIME removes the S/MIME-like wrapper around raw CMS/PKCS7 data
|
||||
func unwrapSMIME(smime []byte) ([]byte, error) {
|
||||
tr := textproto.NewReader(bufio.NewReader(bytes.NewReader(smime)))
|
||||
|
||||
@@ -16,7 +16,6 @@ import (
|
||||
)
|
||||
|
||||
type HTTPHandlers struct {
|
||||
BlueprintHandler http.Handler
|
||||
DEPTokensHandler http.Handler
|
||||
DefineDEPProfileHandler http.Handler
|
||||
AppUploadHandler http.Handler
|
||||
@@ -26,12 +25,6 @@ type HTTPHandlers struct {
|
||||
|
||||
func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
|
||||
h := HTTPHandlers{
|
||||
BlueprintHandler: httptransport.NewServer(
|
||||
endpoints.ApplyBlueprintEndpoint,
|
||||
decodeBlueprintRequest,
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
DEPTokensHandler: httptransport.NewServer(
|
||||
endpoints.ApplyDEPTokensEndpoint,
|
||||
decodeDEPTokensRequest,
|
||||
@@ -86,14 +79,6 @@ func decodeDEPTokensRequest(ctx context.Context, r *http.Request) (interface{},
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeBlueprintRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var bpReq blueprintRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&bpReq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bpReq, nil
|
||||
}
|
||||
|
||||
func decodeDEPProfileRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req depProfileRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
@@ -221,15 +206,6 @@ func encodeBlockDeviceRequest(_ context.Context, r *http.Request, request interf
|
||||
return nil
|
||||
}
|
||||
|
||||
func DecodeBlueprintResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp blueprintResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeDEPTokensResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
|
||||
@@ -36,16 +36,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
var getBlueprintsEndpoint endpoint.Endpoint
|
||||
{
|
||||
getBlueprintsEndpoint = httptransport.NewClient(
|
||||
"GET",
|
||||
copyURL(u, "/v1/blueprints"),
|
||||
encodeRequestWithToken(token, EncodeHTTPGenericRequest),
|
||||
DecodeGetBlueprintsResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var getDEPAccountInfoEndpoint endpoint.Endpoint
|
||||
{
|
||||
@@ -105,7 +95,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
return Endpoints{
|
||||
ListDevicesEndpoint: listDevicesEndpoint,
|
||||
GetDEPTokensEndpoint: getDEPTokensEndpoint,
|
||||
GetBlueprintsEndpoint: getBlueprintsEndpoint,
|
||||
GetDEPAccountInfoEndpoint: getDEPAccountInfoEndpoint,
|
||||
GetDEPDeviceEndpoint: getDEPDeviceDetailsEndpoint,
|
||||
GetDEPProfileEndpoint: getDEPProfilesEndpoint,
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/micromdm/dep"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
@@ -15,7 +14,6 @@ import (
|
||||
type Endpoints struct {
|
||||
ListDevicesEndpoint endpoint.Endpoint
|
||||
GetDEPTokensEndpoint endpoint.Endpoint
|
||||
GetBlueprintsEndpoint endpoint.Endpoint
|
||||
GetDEPAccountInfoEndpoint endpoint.Endpoint
|
||||
GetDEPDeviceEndpoint endpoint.Endpoint
|
||||
GetDEPProfileEndpoint endpoint.Endpoint
|
||||
@@ -58,15 +56,6 @@ func (e Endpoints) GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken, []byt
|
||||
return resp.(depTokenResponse).DEPTokens, resp.(depTokenResponse).DEPPubKey, nil
|
||||
}
|
||||
|
||||
func (e Endpoints) GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]blueprint.Blueprint, error) {
|
||||
request := blueprintsRequest{opt}
|
||||
response, err := e.GetBlueprintsEndpoint(ctx, request.Opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.(blueprintsResponse).Blueprints, response.(blueprintsResponse).Err
|
||||
}
|
||||
|
||||
func (e Endpoints) GetDEPAccountInfo(ctx context.Context) (*dep.Account, error) {
|
||||
request := depAccountInforequest{}
|
||||
response, err := e.GetDEPAccountInfoEndpoint(ctx, request)
|
||||
@@ -138,17 +127,6 @@ func MakeGetDEPTokensEndpoint(svc Service) endpoint.Endpoint {
|
||||
}
|
||||
}
|
||||
|
||||
func MakeGetBlueprintsEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(blueprintsRequest)
|
||||
blueprints, err := svc.GetBlueprints(ctx, req.Opts)
|
||||
return blueprintsResponse{
|
||||
Blueprints: blueprints,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func MakeGetDEPAccountInfoEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
account, err := svc.GetDEPAccountInfo(ctx)
|
||||
@@ -199,14 +177,6 @@ type depTokenResponse struct {
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
type blueprintsRequest struct{ Opts GetBlueprintsOption }
|
||||
type blueprintsResponse struct {
|
||||
Blueprints []blueprint.Blueprint `json:"blueprints"`
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r blueprintsResponse) error() error { return r.Err }
|
||||
|
||||
type depAccountInforequest struct{}
|
||||
type depAccountInfoResponse struct {
|
||||
*dep.Account
|
||||
|
||||
@@ -11,10 +11,8 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/appstore"
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/deptoken"
|
||||
"github.com/micromdm/micromdm/platform/device"
|
||||
"github.com/micromdm/micromdm/platform/profile"
|
||||
"github.com/micromdm/micromdm/platform/pubsub"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
@@ -35,10 +33,6 @@ type ListUsersOption struct {
|
||||
FilterUDID []string
|
||||
}
|
||||
|
||||
type GetBlueprintsOption struct {
|
||||
FilterName string
|
||||
}
|
||||
|
||||
type ListAppsOption struct {
|
||||
FilterName []string `json:"filter_name"`
|
||||
}
|
||||
@@ -47,7 +41,6 @@ type Service interface {
|
||||
ListDevices(ctx context.Context, opt ListDevicesOption) ([]DeviceDTO, error)
|
||||
ListUsers(ctx context.Context, opt ListUsersOption) ([]user.User, error)
|
||||
GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken, []byte, error)
|
||||
GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]blueprint.Blueprint, error)
|
||||
ListApplications(ctx context.Context, opt ListAppsOption) ([]AppDTO, error)
|
||||
DEPService
|
||||
}
|
||||
@@ -56,12 +49,10 @@ type ListService struct {
|
||||
mtx sync.RWMutex
|
||||
DEPClient dep.Client
|
||||
|
||||
Devices *device.DB
|
||||
Blueprints *blueprint.DB
|
||||
Profiles profile.Store
|
||||
Tokens *deptoken.DB
|
||||
Apps appstore.AppStore
|
||||
Users *user.DB
|
||||
Devices *device.DB
|
||||
Tokens *deptoken.DB
|
||||
Apps appstore.AppStore
|
||||
Users *user.DB
|
||||
}
|
||||
|
||||
func (svc *ListService) ListApplications(ctx context.Context, opts ListAppsOption) ([]AppDTO, error) {
|
||||
@@ -155,19 +146,3 @@ func (svc *ListService) GetDEPTokens(ctx context.Context) ([]deptoken.DEPToken,
|
||||
|
||||
return tokens, certBytes, nil
|
||||
}
|
||||
|
||||
func (svc *ListService) GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]blueprint.Blueprint, error) {
|
||||
if opt.FilterName != "" {
|
||||
bp, err := svc.Blueprints.BlueprintByName(opt.FilterName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []blueprint.Blueprint{*bp}, err
|
||||
} else {
|
||||
bps, err := svc.Blueprints.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bps, nil
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
type HTTPHandlers struct {
|
||||
ListDevicesHandler http.Handler
|
||||
GetDEPTokensHandler http.Handler
|
||||
GetBlueprintsHandler http.Handler
|
||||
GetDEPAccountInfoHandler http.Handler
|
||||
GetDEPProfileHandler http.Handler
|
||||
GetDEPDeviceDetailsHandler http.Handler
|
||||
@@ -35,11 +34,6 @@ func MakeHTTPHandlers(ctx context.Context, endpoints Endpoints, opts ...httptran
|
||||
decodeGetDEPTokensRequest,
|
||||
encodeResponse,
|
||||
opts...),
|
||||
GetBlueprintsHandler: httptransport.NewServer(
|
||||
endpoints.GetBlueprintsEndpoint,
|
||||
decodeGetBlueprintsRequest,
|
||||
encodeResponse,
|
||||
opts...),
|
||||
GetDEPAccountInfoHandler: httptransport.NewServer(
|
||||
endpoints.GetDEPAccountInfoEndpoint,
|
||||
decodeDepAccountInfoRequest,
|
||||
@@ -90,17 +84,6 @@ func decodeListUsersRequest(ctx context.Context, r *http.Request) (interface{},
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeGetBlueprintsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var opts GetBlueprintsOption
|
||||
if err := json.NewDecoder(r.Body).Decode(&opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := blueprintsRequest{
|
||||
Opts: opts,
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeDepAccountInfoRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
return nil, nil
|
||||
}
|
||||
@@ -192,15 +175,6 @@ func DecodeGetDEPTokensResponse(_ context.Context, r *http.Response) (interface{
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeGetBlueprintsResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp blueprintsResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeDEPAccountInfoResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
|
||||
@@ -16,17 +16,6 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var removeBlueprintsEndpoint endpoint.Endpoint
|
||||
{
|
||||
removeBlueprintsEndpoint = httptransport.NewClient(
|
||||
"DELETE",
|
||||
copyURL(u, "/v1/blueprints"),
|
||||
encodeRequestWithToken(token, EncodeHTTPGenericRequest),
|
||||
DecodeBlueprintResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var unblockDeviceEndpoint endpoint.Endpoint
|
||||
{
|
||||
unblockDeviceEndpoint = httptransport.NewClient(
|
||||
@@ -39,8 +28,7 @@ func NewClient(instance string, logger log.Logger, token string, opts ...httptra
|
||||
}
|
||||
|
||||
return Endpoints{
|
||||
RemoveBlueprintsEndpoint: removeBlueprintsEndpoint,
|
||||
UnblockDeviceEndpoint: unblockDeviceEndpoint,
|
||||
UnblockDeviceEndpoint: unblockDeviceEndpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,12 @@ import (
|
||||
)
|
||||
|
||||
type Endpoints struct {
|
||||
RemoveBlueprintsEndpoint endpoint.Endpoint
|
||||
UnblockDeviceEndpoint endpoint.Endpoint
|
||||
UnblockDeviceEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
func MakeEndpoints(svc Service) Endpoints {
|
||||
e := Endpoints{
|
||||
RemoveBlueprintsEndpoint: MakeRemoveBlueprintsEndpoint(svc),
|
||||
UnblockDeviceEndpoint: MakeUnblockDeviceEndpoint(svc),
|
||||
UnblockDeviceEndpoint: MakeUnblockDeviceEndpoint(svc),
|
||||
}
|
||||
return e
|
||||
}
|
||||
@@ -28,25 +26,6 @@ func (e Endpoints) UnblockDevice(ctx context.Context, udid string) error {
|
||||
return resp.(unblockDeviceResponse).Err
|
||||
}
|
||||
|
||||
func (e Endpoints) RemoveBlueprints(ctx context.Context, names []string) error {
|
||||
request := blueprintRequest{Names: names}
|
||||
resp, err := e.RemoveBlueprintsEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return resp.(blueprintResponse).Err
|
||||
}
|
||||
|
||||
func MakeRemoveBlueprintsEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(blueprintRequest)
|
||||
err = svc.RemoveBlueprints(ctx, req.Names)
|
||||
return blueprintResponse{
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func MakeUnblockDeviceEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(unblockDeviceRequest)
|
||||
|
||||
@@ -3,28 +3,13 @@ package remove
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/remove"
|
||||
)
|
||||
|
||||
type Service interface {
|
||||
RemoveBlueprints(ctx context.Context, names []string) error
|
||||
UnblockDevice(ctx context.Context, udid string) error
|
||||
}
|
||||
|
||||
type RemoveService struct {
|
||||
Blueprints *blueprint.DB
|
||||
*remove.RemoveService
|
||||
}
|
||||
|
||||
func (svc *RemoveService) RemoveBlueprints(ctx context.Context, names []string) error {
|
||||
// TODO: Wrap deletion(s) in transactions so as to not have
|
||||
// incomplete removals?
|
||||
for _, name := range names {
|
||||
err := svc.Blueprints.Delete(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -14,19 +14,11 @@ import (
|
||||
)
|
||||
|
||||
type HTTPHandlers struct {
|
||||
BlueprintHandler http.Handler
|
||||
ProfileHandler http.Handler
|
||||
UnblockDeviceHandler http.Handler
|
||||
}
|
||||
|
||||
func MakeHTTPHandlers(ctx context.Context, endpoint Endpoints, opts ...httptransport.ServerOption) HTTPHandlers {
|
||||
h := HTTPHandlers{
|
||||
BlueprintHandler: httptransport.NewServer(
|
||||
endpoint.RemoveBlueprintsEndpoint,
|
||||
decodeBlueprintRequest,
|
||||
encodeResponse,
|
||||
opts...,
|
||||
),
|
||||
UnblockDeviceHandler: httptransport.NewServer(
|
||||
endpoint.UnblockDeviceEndpoint,
|
||||
decodeUnblockDeviceRequest,
|
||||
@@ -37,22 +29,6 @@ func MakeHTTPHandlers(ctx context.Context, endpoint Endpoints, opts ...httptrans
|
||||
return h
|
||||
}
|
||||
|
||||
func decodeBlueprintRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var bpReq blueprintRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&bpReq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bpReq, nil
|
||||
}
|
||||
|
||||
func decodeProfileRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req profileRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeUnblockDeviceRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var errBadRoute = errors.New("bad route")
|
||||
var req unblockDeviceRequest
|
||||
@@ -117,24 +93,6 @@ func encodeUnblockDeviceRequest(_ context.Context, r *http.Request, request inte
|
||||
return nil
|
||||
}
|
||||
|
||||
func DecodeBlueprintResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp blueprintResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeProfileResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp profileResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func DecodeUnblockDeviceResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
|
||||
59
platform/blueprint/apply_blueprint.go
Normal file
59
platform/blueprint/apply_blueprint.go
Normal file
@@ -0,0 +1,59 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
func (svc *BlueprintService) ApplyBlueprint(ctx context.Context, bp *Blueprint) error {
|
||||
return svc.store.Save(bp)
|
||||
}
|
||||
|
||||
type applyBlueprintRequest struct {
|
||||
Blueprint *Blueprint `json:"blueprint"`
|
||||
}
|
||||
|
||||
type applyBlueprintResponse struct {
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r applyBlueprintResponse) error() error { return r.Err }
|
||||
|
||||
func decodeApplyBlueprintRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var bpReq applyBlueprintRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&bpReq); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bpReq, nil
|
||||
}
|
||||
|
||||
func decodeApplyBlueprintResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp applyBlueprintResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func MakeApplyBlueprintEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(applyBlueprintRequest)
|
||||
err = svc.ApplyBlueprint(ctx, req.Blueprint)
|
||||
return applyBlueprintResponse{
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e Endpoints) ApplyBlueprint(ctx context.Context, bp *Blueprint) error {
|
||||
request := applyBlueprintRequest{Blueprint: bp}
|
||||
resp, err := e.ApplyBlueprintEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return resp.(applyBlueprintResponse).Err
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package blueprint
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"github.com/boltdb/bolt"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/profile"
|
||||
"github.com/micromdm/micromdm/platform/user"
|
||||
)
|
||||
@@ -46,7 +47,7 @@ func NewDB(
|
||||
return datastore, nil
|
||||
}
|
||||
|
||||
func (db *DB) Create(bp *Blueprint) error {
|
||||
func (db *DB) Create(bp *blueprint.Blueprint) error {
|
||||
_, err := db.BlueprintByName(bp.Name)
|
||||
if err != nil && isNotFound(err) {
|
||||
return errors.New("blueprint must have a unique name")
|
||||
@@ -57,15 +58,15 @@ func (db *DB) Create(bp *Blueprint) error {
|
||||
return db.Save(bp)
|
||||
}
|
||||
|
||||
func (db *DB) List() ([]Blueprint, error) {
|
||||
func (db *DB) List() ([]blueprint.Blueprint, error) {
|
||||
// TODO add filter/limit with ForEach
|
||||
var blueprints []Blueprint
|
||||
var blueprints []blueprint.Blueprint
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(BlueprintBucket))
|
||||
c := b.Cursor()
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
var bp Blueprint
|
||||
if err := UnmarshalBlueprint(v, &bp); err != nil {
|
||||
var bp blueprint.Blueprint
|
||||
if err := blueprint.UnmarshalBlueprint(v, &bp); err != nil {
|
||||
return err
|
||||
}
|
||||
blueprints = append(blueprints, bp)
|
||||
@@ -75,7 +76,7 @@ func (db *DB) List() ([]Blueprint, error) {
|
||||
return blueprints, err
|
||||
}
|
||||
|
||||
func (db *DB) Save(bp *Blueprint) error {
|
||||
func (db *DB) Save(bp *blueprint.Blueprint) error {
|
||||
err := bp.Verify()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -97,7 +98,7 @@ func (db *DB) Save(bp *Blueprint) error {
|
||||
if bkt == nil {
|
||||
return fmt.Errorf("bucket %q not found!", BlueprintBucket)
|
||||
}
|
||||
bpproto, err := MarshalBlueprint(bp)
|
||||
bpproto, err := blueprint.MarshalBlueprint(bp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "marshalling blueprint")
|
||||
}
|
||||
@@ -123,8 +124,8 @@ func (db *DB) Save(bp *Blueprint) error {
|
||||
return tx.Commit()
|
||||
}
|
||||
|
||||
func (db *DB) BlueprintByName(name string) (*Blueprint, error) {
|
||||
var bp Blueprint
|
||||
func (db *DB) BlueprintByName(name string) (*blueprint.Blueprint, error) {
|
||||
var bp blueprint.Blueprint
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(BlueprintBucket))
|
||||
ib := tx.Bucket([]byte(blueprintIndexBucket))
|
||||
@@ -136,7 +137,7 @@ func (db *DB) BlueprintByName(name string) (*Blueprint, error) {
|
||||
if idx == nil {
|
||||
return ¬Found{"Blueprint", fmt.Sprintf("uuid %s", string(idx))}
|
||||
}
|
||||
return UnmarshalBlueprint(v, &bp)
|
||||
return blueprint.UnmarshalBlueprint(v, &bp)
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -144,8 +145,8 @@ func (db *DB) BlueprintByName(name string) (*Blueprint, error) {
|
||||
return &bp, nil
|
||||
}
|
||||
|
||||
func (db *DB) BlueprintsByApplyAt(name string) ([]*Blueprint, error) {
|
||||
var bps []*Blueprint
|
||||
func (db *DB) BlueprintsByApplyAt(name string) ([]*blueprint.Blueprint, error) {
|
||||
var bps []*blueprint.Blueprint
|
||||
err := db.View(func(tx *bolt.Tx) error {
|
||||
b := tx.Bucket([]byte(BlueprintBucket))
|
||||
c := b.Cursor()
|
||||
@@ -153,8 +154,8 @@ func (db *DB) BlueprintsByApplyAt(name string) ([]*Blueprint, error) {
|
||||
// an array of Blueprints or other more efficient means. Looping
|
||||
// over every blueprint is quite inefficient!
|
||||
for k, v := c.First(); k != nil; k, v = c.Next() {
|
||||
var bp Blueprint
|
||||
err := UnmarshalBlueprint(v, &bp)
|
||||
var bp blueprint.Blueprint
|
||||
err := blueprint.UnmarshalBlueprint(v, &bp)
|
||||
if err != nil {
|
||||
fmt.Println("could not Unmarshal Blueprint")
|
||||
continue
|
||||
@@ -1,4 +1,4 @@
|
||||
package blueprint
|
||||
package builtin
|
||||
|
||||
import (
|
||||
"context"
|
||||
@@ -8,13 +8,14 @@ import (
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/micromdm/micromdm/mdm/checkin"
|
||||
"github.com/micromdm/micromdm/platform/blueprint"
|
||||
"github.com/micromdm/micromdm/platform/command"
|
||||
"github.com/micromdm/micromdm/platform/device"
|
||||
"github.com/micromdm/micromdm/platform/profile"
|
||||
"github.com/micromdm/micromdm/platform/pubsub"
|
||||
)
|
||||
|
||||
func (db *DB) ApplyToDevice(ctx context.Context, svc command.Service, bp *Blueprint, udid string) error {
|
||||
func (db *DB) ApplyToDevice(ctx context.Context, svc command.Service, bp *blueprint.Blueprint, udid string) error {
|
||||
var requests []*mdm.CommandRequest
|
||||
for _, uuid := range bp.UserUUID {
|
||||
fmt.Println("Adding user to admin account")
|
||||
@@ -107,7 +108,7 @@ func (db *DB) StartListener(sub pubsub.Subscriber, cmdSvc command.Service) error
|
||||
// skip UserID token updates
|
||||
continue
|
||||
}
|
||||
bps, err := db.BlueprintsByApplyAt(ApplyAtEnroll)
|
||||
bps, err := db.BlueprintsByApplyAt(blueprint.ApplyAtEnroll)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
continue
|
||||
70
platform/blueprint/client.go
Normal file
70
platform/blueprint/client.go
Normal file
@@ -0,0 +1,70 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
)
|
||||
|
||||
func NewHTTPClient(instance, token string, logger log.Logger, opts ...httptransport.ClientOption) (Service, error) {
|
||||
u, err := url.Parse(instance)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var applyBlueprintEndpoint endpoint.Endpoint
|
||||
{
|
||||
applyBlueprintEndpoint = httptransport.NewClient(
|
||||
"PUT",
|
||||
copyURL(u, "/v1/blueprints"),
|
||||
encodeRequestWithToken(token, httptransport.EncodeJSONRequest),
|
||||
decodeApplyBlueprintResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var getBlueprintsEndpoint endpoint.Endpoint
|
||||
{
|
||||
getBlueprintsEndpoint = httptransport.NewClient(
|
||||
"GET",
|
||||
copyURL(u, "/v1/blueprints"),
|
||||
encodeRequestWithToken(token, httptransport.EncodeJSONRequest),
|
||||
decodeGetBlueprintsResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
var removeBlueprintsEndpoint endpoint.Endpoint
|
||||
{
|
||||
removeBlueprintsEndpoint = httptransport.NewClient(
|
||||
"DELETE",
|
||||
copyURL(u, "/v1/blueprints"),
|
||||
encodeRequestWithToken(token, httptransport.EncodeJSONRequest),
|
||||
decodeRemoveBlueprintsResponse,
|
||||
opts...,
|
||||
).Endpoint()
|
||||
}
|
||||
|
||||
return Endpoints{
|
||||
ApplyBlueprintEndpoint: applyBlueprintEndpoint,
|
||||
GetBlueprintsEndpoint: getBlueprintsEndpoint,
|
||||
RemoveBlueprintsEndpoint: removeBlueprintsEndpoint,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func encodeRequestWithToken(token string, next httptransport.EncodeRequestFunc) httptransport.EncodeRequestFunc {
|
||||
return func(ctx context.Context, r *http.Request, request interface{}) error {
|
||||
r.SetBasicAuth("micromdm", token)
|
||||
return next(ctx, r, request)
|
||||
}
|
||||
}
|
||||
|
||||
func copyURL(base *url.URL, path string) *url.URL {
|
||||
next := *base
|
||||
next.Path = path
|
||||
return &next
|
||||
}
|
||||
73
platform/blueprint/get_bplueprints.go
Normal file
73
platform/blueprint/get_bplueprints.go
Normal file
@@ -0,0 +1,73 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
func (svc *BlueprintService) GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]Blueprint, error) {
|
||||
if opt.FilterName != "" {
|
||||
bp, err := svc.store.BlueprintByName(opt.FilterName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return []Blueprint{*bp}, err
|
||||
} else {
|
||||
bps, err := svc.store.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return bps, nil
|
||||
}
|
||||
}
|
||||
|
||||
type getBlueprintsRequest struct{ Opts GetBlueprintsOption }
|
||||
type getBlueprintsResponse struct {
|
||||
Blueprints []Blueprint `json:"blueprints"`
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r getBlueprintsResponse) error() error { return r.Err }
|
||||
|
||||
func decodeGetBlueprintsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var opts GetBlueprintsOption
|
||||
if err := json.NewDecoder(r.Body).Decode(&opts); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req := getBlueprintsRequest{
|
||||
Opts: opts,
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeGetBlueprintsResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp getBlueprintsResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func MakeGetBlueprintsEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(getBlueprintsRequest)
|
||||
blueprints, err := svc.GetBlueprints(ctx, req.Opts)
|
||||
return getBlueprintsResponse{
|
||||
Blueprints: blueprints,
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e Endpoints) GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]Blueprint, error) {
|
||||
request := getBlueprintsRequest{opt}
|
||||
response, err := e.GetBlueprintsEndpoint(ctx, request.Opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return response.(getBlueprintsResponse).Blueprints, response.(getBlueprintsResponse).Err
|
||||
}
|
||||
65
platform/blueprint/remove_blueprints.go
Normal file
65
platform/blueprint/remove_blueprints.go
Normal file
@@ -0,0 +1,65 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
)
|
||||
|
||||
func (svc *BlueprintService) RemoveBlueprints(ctx context.Context, names []string) error {
|
||||
for _, name := range names {
|
||||
err := svc.store.Delete(name)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type removeBlueprintsRequest struct {
|
||||
Names []string `json:"names"`
|
||||
}
|
||||
|
||||
type removeBlueprintsResponse struct {
|
||||
Err error `json:"err,omitempty"`
|
||||
}
|
||||
|
||||
func (r removeBlueprintsResponse) error() error { return r.Err }
|
||||
|
||||
func decodeRemoveBlueprintsRequest(ctx context.Context, r *http.Request) (interface{}, error) {
|
||||
var req removeBlueprintsRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req, nil
|
||||
}
|
||||
|
||||
func decodeRemoveBlueprintsResponse(_ context.Context, r *http.Response) (interface{}, error) {
|
||||
if r.StatusCode != http.StatusOK {
|
||||
return nil, errorDecoder(r)
|
||||
}
|
||||
var resp removeBlueprintsResponse
|
||||
err := json.NewDecoder(r.Body).Decode(&resp)
|
||||
return resp, err
|
||||
}
|
||||
|
||||
func MakeRemoveBlueprintsEndpoint(svc Service) endpoint.Endpoint {
|
||||
return func(ctx context.Context, request interface{}) (response interface{}, err error) {
|
||||
req := request.(removeBlueprintsRequest)
|
||||
err = svc.RemoveBlueprints(ctx, req.Names)
|
||||
return removeBlueprintsResponse{
|
||||
Err: err,
|
||||
}, nil
|
||||
}
|
||||
}
|
||||
|
||||
func (e Endpoints) RemoveBlueprints(ctx context.Context, names []string) error {
|
||||
request := removeBlueprintsRequest{Names: names}
|
||||
resp, err := e.RemoveBlueprintsEndpoint(ctx, request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return resp.(removeBlueprintsResponse).Err
|
||||
}
|
||||
76
platform/blueprint/server.go
Normal file
76
platform/blueprint/server.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/go-kit/kit/endpoint"
|
||||
"github.com/go-kit/kit/log"
|
||||
httptransport "github.com/go-kit/kit/transport/http"
|
||||
"github.com/gorilla/mux"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type Endpoints struct {
|
||||
ApplyBlueprintEndpoint endpoint.Endpoint
|
||||
GetBlueprintsEndpoint endpoint.Endpoint
|
||||
RemoveBlueprintsEndpoint endpoint.Endpoint
|
||||
}
|
||||
|
||||
func MakeServerEndpoints(s Service) Endpoints {
|
||||
return Endpoints{
|
||||
GetBlueprintsEndpoint: MakeGetBlueprintsEndpoint(s),
|
||||
ApplyBlueprintEndpoint: MakeApplyBlueprintEndpoint(s),
|
||||
}
|
||||
}
|
||||
|
||||
func MakeHTTPHandler(e Endpoints, logger log.Logger) http.Handler {
|
||||
options := []httptransport.ServerOption{
|
||||
httptransport.ServerErrorLogger(logger),
|
||||
}
|
||||
|
||||
r := mux.NewRouter()
|
||||
|
||||
// PUT /v1/blueprints create or replace a blueprint on the server
|
||||
// GET /v1/blueprints get a list of blueprints managed by the server
|
||||
// DELETE /v1/blueprints remove one or more blueprints from the server
|
||||
|
||||
r.Methods("PUT").Path("/v1/blueprints").Handler(httptransport.NewServer(
|
||||
e.ApplyBlueprintEndpoint,
|
||||
decodeApplyBlueprintRequest,
|
||||
httptransport.EncodeJSONResponse,
|
||||
options...,
|
||||
))
|
||||
|
||||
r.Methods("GET").Path("/v1/blueprints").Handler(httptransport.NewServer(
|
||||
e.GetBlueprintsEndpoint,
|
||||
decodeGetBlueprintsRequest,
|
||||
httptransport.EncodeJSONResponse,
|
||||
options...,
|
||||
))
|
||||
|
||||
r.Methods("DELETE").Path("/v1/blueprints").Handler(httptransport.NewServer(
|
||||
e.RemoveBlueprintsEndpoint,
|
||||
decodeRemoveBlueprintsRequest,
|
||||
httptransport.EncodeJSONResponse,
|
||||
options...,
|
||||
))
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
type errorWrapper struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
type errorer interface {
|
||||
error() error
|
||||
}
|
||||
|
||||
func errorDecoder(r *http.Response) error {
|
||||
var w errorWrapper
|
||||
if err := json.NewDecoder(r.Body).Decode(&w); err != nil {
|
||||
return err
|
||||
}
|
||||
return errors.New(w.Error)
|
||||
}
|
||||
30
platform/blueprint/service.go
Normal file
30
platform/blueprint/service.go
Normal file
@@ -0,0 +1,30 @@
|
||||
package blueprint
|
||||
|
||||
import (
|
||||
"context"
|
||||
)
|
||||
|
||||
type GetBlueprintsOption struct {
|
||||
FilterName string
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
ApplyBlueprint(ctx context.Context, bp *Blueprint) error
|
||||
GetBlueprints(ctx context.Context, opt GetBlueprintsOption) ([]Blueprint, error)
|
||||
RemoveBlueprints(ctx context.Context, names []string) error
|
||||
}
|
||||
|
||||
type Store interface {
|
||||
Save(*Blueprint) error
|
||||
BlueprintByName(name string) (*Blueprint, error)
|
||||
List() ([]Blueprint, error)
|
||||
Delete(string) error
|
||||
}
|
||||
|
||||
type BlueprintService struct {
|
||||
store Store
|
||||
}
|
||||
|
||||
func New(store Store) *BlueprintService {
|
||||
return &BlueprintService{store: store}
|
||||
}
|
||||
Reference in New Issue
Block a user