Skip to content
This repository has been archived by the owner on Dec 15, 2020. It is now read-only.

Commit

Permalink
Add ability to modify labels (#1202)
Browse files Browse the repository at this point in the history
  • Loading branch information
murphybytes authored Feb 12, 2017
1 parent 77243b3 commit 6dc56ad
Show file tree
Hide file tree
Showing 14 changed files with 305 additions and 1 deletion.
22 changes: 22 additions & 0 deletions server/datastore/datastore_labels_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,3 +355,25 @@ func testListUniqueHostsInLabels(t *testing.T, db kolide.Datastore) {
require.Len(t, labels, 2)

}

func testSaveLabel(t *testing.T, db kolide.Datastore) {
if db.Name() == "inmem" {
t.Skip("inmem is being deprecated")
}
label := &kolide.Label{
Name: "my label",
Description: "a label",
Query: "select 1 from processes;",
Platform: "darwin",
}
label, err := db.NewLabel(label)
require.Nil(t, err)
label.Name = "changed name"
label.Description = "changed description"
_, err = db.SaveLabel(label)
require.Nil(t, err)
saved, err := db.Label(label.ID)
require.Nil(t, err)
assert.Equal(t, label.Name, saved.Name)
assert.Equal(t, label.Description, saved.Description)
}
1 change: 1 addition & 0 deletions server/datastore/datastore_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,5 @@ var testFunctions = [...]func(*testing.T, kolide.Datastore){
testIdempotentDeleteHost,
testChangeEmail,
testLicense,
testSaveLabel,
}
4 changes: 4 additions & 0 deletions server/datastore/inmem/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,3 +224,7 @@ func (d *Datastore) ListUniqueHostsInLabels(labels []uint) ([]kolide.Host, error

return hosts, nil
}

func (d *Datastore) SaveLabel(label *kolide.Label) (*kolide.Label, error) {
panic("inmem is being deprecated")
}
14 changes: 14 additions & 0 deletions server/datastore/mysql/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -314,3 +314,17 @@ func (d *Datastore) SearchLabels(query string, omit ...uint) ([]kolide.Label, er
}
return matches, nil
}

func (d *Datastore) SaveLabel(label *kolide.Label) (*kolide.Label, error) {
query := `
UPDATE labels SET
name = ?,
description = ?
WHERE id = ?
`
_, err := d.db.Exec(query, label.Name, label.Description, label.ID)
if err != nil {
return nil, errors.Wrap(err, "saving label")
}
return label, nil
}
13 changes: 13 additions & 0 deletions server/kolide/labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,18 +33,31 @@ type LabelStore interface {
ListUniqueHostsInLabels(labels []uint) ([]Host, error)

SearchLabels(query string, omit ...uint) ([]Label, error)

// SaveLabel allows modification of a label's name and/or description
SaveLabel(label *Label) (*Label, error)
}

type LabelService interface {
ListLabels(ctx context.Context, opt ListOptions) (labels []*Label, err error)
GetLabel(ctx context.Context, id uint) (label *Label, err error)
NewLabel(ctx context.Context, p LabelPayload) (label *Label, err error)
DeleteLabel(ctx context.Context, id uint) (err error)

// ModifyLabel is used to change editable fields belonging to a Label
ModifyLabel(ctx context.Context, id uint, payload ModifyLabelPayload) (*Label, error)

// HostIDsForLabel returns ids of hosts that belong to the label identified
// by lid
HostIDsForLabel(lid uint) ([]uint, error)
}

// ModifyLabelPayload is used to change editable fields for a Label
type ModifyLabelPayload struct {
Name *string `json:"name"`
Description *string `json:"description"`
}

type LabelPayload struct {
Name *string `json:"name"`
Query *string `json:"query"`
Expand Down
3 changes: 2 additions & 1 deletion server/mock/datastore.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,14 @@ package mock
//go:generate mockimpl -o datastore_invites.go "s *InviteStore" "kolide.InviteStore"
//go:generate mockimpl -o datastore_appconfig.go "s *AppConfigStore" "kolide.AppConfigStore"
//go:generate mockimpl -o datastore_licenses.go "s *LicenseStore" "kolide.LicenseStore"
//go:generate mockimpl -o datastore_labels.go "s *LabelStore" "kolide.LabelStore"

import "github.com/kolide/kolide/server/kolide"

var _ kolide.Datastore = (*Store)(nil)

type Store struct {
kolide.HostStore
kolide.LabelStore
kolide.PackStore
kolide.CampaignStore
kolide.SessionStore
Expand All @@ -26,6 +26,7 @@ type Store struct {
InviteStore
UserStore
AppConfigStore
LabelStore
}

func (m *Store) Drop() error {
Expand Down
123 changes: 123 additions & 0 deletions server/mock/datastore_labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// Automatically generated by mockimpl. DO NOT EDIT!

package mock

import (
"time"

"github.com/kolide/kolide/server/kolide"
)

var _ kolide.LabelStore = (*LabelStore)(nil)

type NewLabelFunc func(Label *kolide.Label) (*kolide.Label, error)

type DeleteLabelFunc func(lid uint) error

type LabelFunc func(lid uint) (*kolide.Label, error)

type ListLabelsFunc func(opt kolide.ListOptions) ([]*kolide.Label, error)

type LabelQueriesForHostFunc func(host *kolide.Host, cutoff time.Time) (map[string]string, error)

type RecordLabelQueryExecutionsFunc func(host *kolide.Host, results map[uint]bool, t time.Time) error

type ListLabelsForHostFunc func(hid uint) ([]kolide.Label, error)

type ListHostsInLabelFunc func(lid uint) ([]kolide.Host, error)

type ListUniqueHostsInLabelsFunc func(labels []uint) ([]kolide.Host, error)

type SearchLabelsFunc func(query string, omit ...uint) ([]kolide.Label, error)

type SaveLabelFunc func(label *kolide.Label) (*kolide.Label, error)

type LabelStore struct {
NewLabelFunc NewLabelFunc
NewLabelFuncInvoked bool

DeleteLabelFunc DeleteLabelFunc
DeleteLabelFuncInvoked bool

LabelFunc LabelFunc
LabelFuncInvoked bool

ListLabelsFunc ListLabelsFunc
ListLabelsFuncInvoked bool

LabelQueriesForHostFunc LabelQueriesForHostFunc
LabelQueriesForHostFuncInvoked bool

RecordLabelQueryExecutionsFunc RecordLabelQueryExecutionsFunc
RecordLabelQueryExecutionsFuncInvoked bool

ListLabelsForHostFunc ListLabelsForHostFunc
ListLabelsForHostFuncInvoked bool

ListHostsInLabelFunc ListHostsInLabelFunc
ListHostsInLabelFuncInvoked bool

ListUniqueHostsInLabelsFunc ListUniqueHostsInLabelsFunc
ListUniqueHostsInLabelsFuncInvoked bool

SearchLabelsFunc SearchLabelsFunc
SearchLabelsFuncInvoked bool

SaveLabelFunc SaveLabelFunc
SaveLabelFuncInvoked bool
}

func (s *LabelStore) NewLabel(Label *kolide.Label) (*kolide.Label, error) {
s.NewLabelFuncInvoked = true
return s.NewLabelFunc(Label)
}

func (s *LabelStore) DeleteLabel(lid uint) error {
s.DeleteLabelFuncInvoked = true
return s.DeleteLabelFunc(lid)
}

func (s *LabelStore) Label(lid uint) (*kolide.Label, error) {
s.LabelFuncInvoked = true
return s.LabelFunc(lid)
}

func (s *LabelStore) ListLabels(opt kolide.ListOptions) ([]*kolide.Label, error) {
s.ListLabelsFuncInvoked = true
return s.ListLabelsFunc(opt)
}

func (s *LabelStore) LabelQueriesForHost(host *kolide.Host, cutoff time.Time) (map[string]string, error) {
s.LabelQueriesForHostFuncInvoked = true
return s.LabelQueriesForHostFunc(host, cutoff)
}

func (s *LabelStore) RecordLabelQueryExecutions(host *kolide.Host, results map[uint]bool, t time.Time) error {
s.RecordLabelQueryExecutionsFuncInvoked = true
return s.RecordLabelQueryExecutionsFunc(host, results, t)
}

func (s *LabelStore) ListLabelsForHost(hid uint) ([]kolide.Label, error) {
s.ListLabelsForHostFuncInvoked = true
return s.ListLabelsForHostFunc(hid)
}

func (s *LabelStore) ListHostsInLabel(lid uint) ([]kolide.Host, error) {
s.ListHostsInLabelFuncInvoked = true
return s.ListHostsInLabelFunc(lid)
}

func (s *LabelStore) ListUniqueHostsInLabels(labels []uint) ([]kolide.Host, error) {
s.ListUniqueHostsInLabelsFuncInvoked = true
return s.ListUniqueHostsInLabelsFunc(labels)
}

func (s *LabelStore) SearchLabels(query string, omit ...uint) ([]kolide.Label, error) {
s.SearchLabelsFuncInvoked = true
return s.SearchLabelsFunc(query, omit...)
}

func (s *LabelStore) SaveLabel(label *kolide.Label) (*kolide.Label, error) {
s.SaveLabelFuncInvoked = true
return s.SaveLabelFunc(label)
}
23 changes: 23 additions & 0 deletions server/service/endpoint_labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,26 @@ func makeDeleteLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
return deleteLabelResponse{}, nil
}
}

type modifyLabelRequest struct {
ID uint
payload kolide.ModifyLabelPayload
}

type modifyLabelResponse struct {
Label *kolide.Label `json:"label"`
Err error `json:"error,omitempty"`
}

func (r modifyLabelResponse) error() error { return r.Err }

func makeModifyLabelEndpoint(svc kolide.Service) endpoint.Endpoint {
return func(ctx context.Context, request interface{}) (interface{}, error) {
req := request.(modifyLabelRequest)
label, err := svc.ModifyLabel(ctx, req.ID, req.payload)
if err != nil {
return modifyLabelResponse{Err: err}, nil
}
return modifyLabelResponse{Label: label}, err
}
}
5 changes: 5 additions & 0 deletions server/service/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type KolideEndpoints struct {
ListLabels endpoint.Endpoint
CreateLabel endpoint.Endpoint
DeleteLabel endpoint.Endpoint
ModifyLabel endpoint.Endpoint
GetHost endpoint.Endpoint
DeleteHost endpoint.Endpoint
ListHosts endpoint.Endpoint
Expand Down Expand Up @@ -141,6 +142,7 @@ func MakeKolideServerEndpoints(svc kolide.Service, jwtKey string) KolideEndpoint
ListLabels: authenticatedUser(jwtKey, svc, makeListLabelsEndpoint(svc)),
CreateLabel: authenticatedUser(jwtKey, svc, makeCreateLabelEndpoint(svc)),
DeleteLabel: authenticatedUser(jwtKey, svc, makeDeleteLabelEndpoint(svc)),
ModifyLabel: authenticatedUser(jwtKey, svc, makeModifyLabelEndpoint(svc)),
SearchTargets: authenticatedUser(jwtKey, svc, makeSearchTargetsEndpoint(svc)),
GetOptions: authenticatedUser(jwtKey, svc, mustBeAdmin(makeGetOptionsEndpoint(svc))),
ModifyOptions: authenticatedUser(jwtKey, svc, mustBeAdmin(makeModifyOptionsEndpoint(svc))),
Expand Down Expand Up @@ -210,6 +212,7 @@ type kolideHandlers struct {
ListLabels http.Handler
CreateLabel http.Handler
DeleteLabel http.Handler
ModifyLabel http.Handler
GetHost http.Handler
DeleteHost http.Handler
ListHosts http.Handler
Expand Down Expand Up @@ -279,6 +282,7 @@ func makeKolideKitHandlers(ctx context.Context, e KolideEndpoints, opts []kithtt
ListLabels: newServer(e.ListLabels, decodeListLabelsRequest),
CreateLabel: newServer(e.CreateLabel, decodeCreateLabelRequest),
DeleteLabel: newServer(e.DeleteLabel, decodeDeleteLabelRequest),
ModifyLabel: newServer(e.ModifyLabel, decodeModifyLabelRequest),
GetHost: newServer(e.GetHost, decodeGetHostRequest),
DeleteHost: newServer(e.DeleteHost, decodeDeleteHostRequest),
ListHosts: newServer(e.ListHosts, decodeListHostsRequest),
Expand Down Expand Up @@ -385,6 +389,7 @@ func attachKolideAPIRoutes(r *mux.Router, h *kolideHandlers) {
r.Handle("/api/v1/kolide/labels", h.ListLabels).Methods("GET").Name("list_labels")
r.Handle("/api/v1/kolide/labels", h.CreateLabel).Methods("POST").Name("create_label")
r.Handle("/api/v1/kolide/labels/{id}", h.DeleteLabel).Methods("DELETE").Name("delete_label")
r.Handle("/api/v1/kolide/labels/{id}", h.ModifyLabel).Methods("PATCH").Name("modify_label")

r.Handle("/api/v1/kolide/hosts", h.ListHosts).Methods("GET").Name("list_hosts")
r.Handle("/api/v1/kolide/host_summary", h.GetHostSummary).Methods("GET").Name("get_host_summary")
Expand Down
18 changes: 18 additions & 0 deletions server/service/logging_labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,24 @@ import (
"golang.org/x/net/context"
)

func (mw loggingMiddleware) ModifyLabel(ctx context.Context, id uint, p kolide.ModifyLabelPayload) (*kolide.Label, error) {
var (
label *kolide.Label
err error
)

defer func(begin time.Time) {
mw.logger.Log(
"method", "ModifyLabel",
"err", err,
"took", time.Since(begin),
)
}(time.Now())

label, err = mw.Service.ModifyLabel(ctx, id, p)
return label, err
}

func (mw loggingMiddleware) ListLabels(ctx context.Context, opt kolide.ListOptions) ([]*kolide.Label, error) {
var (
labels []*kolide.Label
Expand Down
24 changes: 24 additions & 0 deletions server/service/metrics_labels.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package service

import (
"fmt"
"time"

"github.com/kolide/kolide/server/kolide"
"golang.org/x/net/context"
)

func (mw metricsMiddleware) ModifyLabel(ctx context.Context, id uint, p kolide.ModifyLabelPayload) (*kolide.Label, error) {
var (
lic *kolide.Label
err error
)
defer func(begin time.Time) {
lvs := []string{"method", "ModifyLabel", "error", fmt.Sprint(err != nil)}
mw.requestCount.With(lvs...).Add(1)
mw.requestLatency.With(lvs...).Observe(time.Since(begin).Seconds())
}(time.Now())
lic, err = mw.Service.ModifyLabel(ctx, id, p)
return lic, err

}
14 changes: 14 additions & 0 deletions server/service/service_labels.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,17 @@ func (svc service) HostIDsForLabel(lid uint) ([]uint, error) {
}
return ids, nil
}

func (svc service) ModifyLabel(ctx context.Context, id uint, payload kolide.ModifyLabelPayload) (*kolide.Label, error) {
label, err := svc.ds.Label(id)
if err != nil {
return nil, err
}
if payload.Name != nil {
label.Name = *payload.Name
}
if payload.Description != nil {
label.Description = *payload.Description
}
return svc.ds.SaveLabel(label)
}
Loading

0 comments on commit 6dc56ad

Please sign in to comment.