package service import ( "github.com/go-kit/kit/endpoint" "github.com/kolide/kolide/server/kolide" "golang.org/x/net/context" ) type packResponse struct { kolide.Pack QueryCount uint `json:"query_count"` // All current hosts in the pack. Hosts which are selected explicty and // hosts which are part of a label. TotalHostsCount uint `json:"total_hosts_count"` // IDs of hosts which were explicitly selected. HostIDs []uint `json:"host_ids"` LabelIDs []uint `json:"label_ids"` } func packResponseForPack(ctx context.Context, svc kolide.Service, pack kolide.Pack) (*packResponse, error) { opts := kolide.ListOptions{} queries, err := svc.GetScheduledQueriesInPack(ctx, pack.ID, opts) if err != nil { return nil, err } // ListHostsInPack returns hosts which were explicitly set + // the hosts which are part of a packs labels. We want both for the totals, // but only the explicit host ids for the host_id field. allHosts, err := svc.ListHostsInPack(ctx, pack.ID, opts) if err != nil { return nil, err } totalHostCount := uint(len(allHosts)) hosts, err := svc.ListExplicitHostsInPack(ctx, pack.ID, opts) if err != nil { return nil, err } hostIDs := make([]uint, len(hosts), len(hosts)) for i, host := range hosts { hostIDs[i] = host.ID } labels, err := svc.ListLabelsForPack(ctx, pack.ID) labelIDs := make([]uint, len(labels), len(labels)) for i, label := range labels { labelIDs[i] = label.ID } if err != nil { return nil, err } return &packResponse{ Pack: pack, QueryCount: uint(len(queries)), TotalHostsCount: totalHostCount, HostIDs: hostIDs, LabelIDs: labelIDs, }, nil } //////////////////////////////////////////////////////////////////////////////// // Get Pack //////////////////////////////////////////////////////////////////////////////// type getPackRequest struct { ID uint } type getPackResponse struct { Pack packResponse `json:"pack,omitempty"` Err error `json:"error,omitempty"` } func (r getPackResponse) error() error { return r.Err } func makeGetPackEndpoint(svc kolide.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(getPackRequest) pack, err := svc.GetPack(ctx, req.ID) if err != nil { return getPackResponse{Err: err}, nil } resp, err := packResponseForPack(ctx, svc, *pack) if err != nil { return getPackResponse{Err: err}, nil } return getPackResponse{ Pack: *resp, }, nil } } //////////////////////////////////////////////////////////////////////////////// // List Packs //////////////////////////////////////////////////////////////////////////////// type listPacksRequest struct { ListOptions kolide.ListOptions } type listPacksResponse struct { Packs []packResponse `json:"packs"` Err error `json:"error,omitempty"` } func (r listPacksResponse) error() error { return r.Err } func makeListPacksEndpoint(svc kolide.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(listPacksRequest) packs, err := svc.ListPacks(ctx, req.ListOptions) if err != nil { return getPackResponse{Err: err}, nil } resp := listPacksResponse{Packs: make([]packResponse, len(packs), len(packs))} for i, pack := range packs { packResp, err := packResponseForPack(ctx, svc, *pack) if err != nil { return getPackResponse{Err: err}, nil } resp.Packs[i] = *packResp } return resp, nil } } //////////////////////////////////////////////////////////////////////////////// // Create Pack //////////////////////////////////////////////////////////////////////////////// type createPackRequest struct { payload kolide.PackPayload } type createPackResponse struct { Pack packResponse `json:"pack,omitempty"` Err error `json:"error,omitempty"` } func (r createPackResponse) error() error { return r.Err } func makeCreatePackEndpoint(svc kolide.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(createPackRequest) pack, err := svc.NewPack(ctx, req.payload) if err != nil { return createPackResponse{Err: err}, nil } resp, err := packResponseForPack(ctx, svc, *pack) if err != nil { return createPackResponse{Err: err}, nil } return createPackResponse{ Pack: *resp, }, nil } } //////////////////////////////////////////////////////////////////////////////// // Modify Pack //////////////////////////////////////////////////////////////////////////////// type modifyPackRequest struct { ID uint payload kolide.PackPayload } type modifyPackResponse struct { Pack packResponse `json:"pack,omitempty"` Err error `json:"error,omitempty"` } func (r modifyPackResponse) error() error { return r.Err } func makeModifyPackEndpoint(svc kolide.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(modifyPackRequest) pack, err := svc.ModifyPack(ctx, req.ID, req.payload) if err != nil { return modifyPackResponse{Err: err}, nil } resp, err := packResponseForPack(ctx, svc, *pack) if err != nil { return modifyPackResponse{Err: err}, nil } return modifyPackResponse{ Pack: *resp, }, nil } } //////////////////////////////////////////////////////////////////////////////// // Delete Pack //////////////////////////////////////////////////////////////////////////////// type deletePackRequest struct { ID uint } type deletePackResponse struct { Err error `json:"error,omitempty"` } func (r deletePackResponse) error() error { return r.Err } func makeDeletePackEndpoint(svc kolide.Service) endpoint.Endpoint { return func(ctx context.Context, request interface{}) (interface{}, error) { req := request.(deletePackRequest) err := svc.DeletePack(ctx, req.ID) if err != nil { return deletePackResponse{Err: err}, nil } return deletePackResponse{}, nil } }