mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 17:05:18 +00:00
c6c5e65a7d
Support the same query syntax as the hosts endpoint, here also bounded by the membership of the label.
202 lines
6.7 KiB
Go
202 lines
6.7 KiB
Go
package kolide
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
type LabelStore interface {
|
|
// ApplyLabelSpecs applies a list of LabelSpecs to the datastore,
|
|
// creating and updating labels as necessary.
|
|
ApplyLabelSpecs(specs []*LabelSpec) error
|
|
// GetLabelSpecs returns all of the stored LabelSpecs.
|
|
GetLabelSpecs() ([]*LabelSpec, error)
|
|
// GetLabelSpec returns the spec for the named label.
|
|
GetLabelSpec(name string) (*LabelSpec, error)
|
|
|
|
// Label methods
|
|
NewLabel(Label *Label, opts ...OptionalArg) (*Label, error)
|
|
SaveLabel(label *Label) (*Label, error)
|
|
DeleteLabel(name string) error
|
|
Label(lid uint) (*Label, error)
|
|
ListLabels(opt ListOptions) ([]*Label, error)
|
|
|
|
// LabelQueriesForHost returns the label queries that should be executed
|
|
// for the given host. The cutoff is the minimum timestamp a query
|
|
// execution should have to be considered "fresh". Executions that are
|
|
// not fresh will be repeated. Results are returned in a map of label
|
|
// id -> query
|
|
LabelQueriesForHost(host *Host, cutoff time.Time) (map[string]string, error)
|
|
|
|
// RecordLabelQueryExecutions saves the results of label queries. The
|
|
// results map is a map of label id -> whether or not the label
|
|
// matches. The time parameter is the timestamp to save with the query
|
|
// execution.
|
|
RecordLabelQueryExecutions(host *Host, results map[uint]bool, t time.Time) error
|
|
|
|
// LabelsForHost returns the labels that the given host is in.
|
|
ListLabelsForHost(hid uint) ([]Label, error)
|
|
|
|
// ListHostsInLabel returns a slice of hosts in the label with the
|
|
// given ID.
|
|
ListHostsInLabel(lid uint, opt HostListOptions) ([]Host, error)
|
|
|
|
// ListUniqueHostsInLabels returns a slice of all of the hosts in the
|
|
// given label IDs. A host will only appear once in the results even if
|
|
// it is in multiple of the provided labels.
|
|
ListUniqueHostsInLabels(labels []uint) ([]Host, error)
|
|
|
|
SearchLabels(query string, omit ...uint) ([]Label, error)
|
|
|
|
// LabelIDsByName Retrieve the IDs associated with the given labels
|
|
LabelIDsByName(labels []string) ([]uint, error)
|
|
}
|
|
|
|
type LabelService interface {
|
|
// ApplyLabelSpecs applies a list of LabelSpecs to the datastore,
|
|
// creating and updating labels as necessary.
|
|
ApplyLabelSpecs(ctx context.Context, specs []*LabelSpec) error
|
|
// GetLabelSpecs returns all of the stored LabelSpecs.
|
|
GetLabelSpecs(ctx context.Context) ([]*LabelSpec, error)
|
|
// GetLabelSpec gets the spec for the label with the given name.
|
|
GetLabelSpec(ctx context.Context, name string) (*LabelSpec, error)
|
|
|
|
NewLabel(ctx context.Context, p LabelPayload) (label *Label, err error)
|
|
ModifyLabel(ctx context.Context, id uint, payload ModifyLabelPayload) (*Label, error)
|
|
ListLabels(ctx context.Context, opt ListOptions) (labels []*Label, err error)
|
|
GetLabel(ctx context.Context, id uint) (label *Label, err error)
|
|
|
|
DeleteLabel(ctx context.Context, name string) (err error)
|
|
// DeleteLabelByID is for backwards compatibility with the UI
|
|
DeleteLabelByID(ctx context.Context, id uint) (err error)
|
|
|
|
// ListHostsInLabel returns a slice of hosts in the label with the
|
|
// given ID.
|
|
ListHostsInLabel(ctx context.Context, lid uint, opt HostListOptions) ([]Host, error)
|
|
|
|
// LabelsForHost returns the labels that the given host is in.
|
|
ListLabelsForHost(ctx context.Context, hid uint) ([]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"`
|
|
Platform *string `json:"platform"`
|
|
Description *string `json:"description"`
|
|
}
|
|
|
|
// LabelType is used to catagorize the kind of label
|
|
type LabelType uint
|
|
|
|
const (
|
|
// LabelTypeRegular is for user created labels that can be modified.
|
|
LabelTypeRegular LabelType = iota
|
|
// LabelTypeBuiltIn is for labels built into Fleet that cannot be
|
|
// modified by users.
|
|
LabelTypeBuiltIn
|
|
)
|
|
|
|
func (t LabelType) MarshalJSON() ([]byte, error) {
|
|
switch t {
|
|
case LabelTypeRegular:
|
|
return []byte(`"regular"`), nil
|
|
case LabelTypeBuiltIn:
|
|
return []byte(`"builtin"`), nil
|
|
default:
|
|
return nil, errors.Errorf("invalid LabelType: %d", t)
|
|
}
|
|
}
|
|
|
|
func (t *LabelType) UnmarshalJSON(b []byte) error {
|
|
switch string(b) {
|
|
case `"regular"`, "0":
|
|
*t = LabelTypeRegular
|
|
case `"builtin"`, "1":
|
|
*t = LabelTypeBuiltIn
|
|
default:
|
|
return errors.Errorf("invalid LabelType: %s", string(b))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// LabelMembershipType sets how the membership of the label is determined.
|
|
type LabelMembershipType uint
|
|
|
|
const (
|
|
// LabelTypeDynamic indicates that the label is populated dynamically (by
|
|
// the execution of a label query).
|
|
LabelMembershipTypeDynamic LabelMembershipType = iota
|
|
// LabelTypeManual indicates that the label is populated manually.
|
|
LabelMembershipTypeManual
|
|
)
|
|
|
|
func (t LabelMembershipType) MarshalJSON() ([]byte, error) {
|
|
switch t {
|
|
case LabelMembershipTypeDynamic:
|
|
return []byte(`"dynamic"`), nil
|
|
case LabelMembershipTypeManual:
|
|
return []byte(`"manual"`), nil
|
|
default:
|
|
return nil, errors.Errorf("invalid LabelMembershipType: %d", t)
|
|
}
|
|
}
|
|
|
|
func (t *LabelMembershipType) UnmarshalJSON(b []byte) error {
|
|
switch string(b) {
|
|
case `"dynamic"`:
|
|
*t = LabelMembershipTypeDynamic
|
|
case `"manual"`:
|
|
*t = LabelMembershipTypeManual
|
|
default:
|
|
return errors.Errorf("invalid LabelMembershipType: %s", string(b))
|
|
}
|
|
return nil
|
|
}
|
|
|
|
type Label struct {
|
|
UpdateCreateTimestamps
|
|
ID uint `json:"id"`
|
|
Name string `json:"name"`
|
|
Description string `json:"description,omitempty"`
|
|
Query string `json:"query"`
|
|
Platform string `json:"platform,omitempty"`
|
|
LabelType LabelType `json:"label_type" db:"label_type"`
|
|
LabelMembershipType LabelMembershipType `json:"label_membership_type" db:"label_membership_type"`
|
|
HostCount int `json:"host_count,omitempty" db:"host_count"`
|
|
}
|
|
|
|
const (
|
|
LabelKind = "label"
|
|
)
|
|
|
|
type LabelQueryExecution struct {
|
|
ID uint
|
|
UpdatedAt time.Time
|
|
Matches bool
|
|
LabelID uint
|
|
HostID uint
|
|
}
|
|
|
|
type LabelSpec struct {
|
|
ID uint
|
|
Name string `json:"name"`
|
|
Description string `json:"description"`
|
|
Query string `json:"query"`
|
|
Platform string `json:"platform,omitempty"`
|
|
LabelType LabelType `json:"label_type,omitempty" db:"label_type"`
|
|
LabelMembershipType LabelMembershipType `json:"label_membership_type" db:"label_membership_type"`
|
|
Hosts []string `json:"hosts,omitempty"`
|
|
}
|