Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
267 changes: 267 additions & 0 deletions api/aggregate-alerts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,267 @@
package api

import (
"fmt"
graphql "github.com/cli/shurcooL-graphql"
"github.com/humio/cli/api/internal/humiographql"
)

type AggregateAlert struct {
ID string `graphql:"id" yaml:"-" json:"id"`
Name string `graphql:"name" yaml:"name" json:"name"`
Description string `graphql:"description" yaml:"description,omitempty" json:"description,omitempty"`
QueryString string `graphql:"queryString" yaml:"queryString" json:"queryString"`
SearchIntervalSeconds int `graphql:"searchIntervalSeconds" yaml:"searchIntervalSeconds" json:"searchIntervalSeconds"`
ActionNames []string `graphql:"actionNames" yaml:"actionNames" json:"actionNames"`
Labels []string `graphql:"labels" yaml:"labels" json:"labels"`
Enabled bool `graphql:"enabled" yaml:"enabled" json:"enabled"`
ThrottleField string `graphql:"throttleField" yaml:"throttleField,omitempty" json:"throttleField,omitempty"`
ThrottleTimeSeconds int `graphql:"throttleTimeSeconds" yaml:"throttleTimeSeconds" json:"throttleTimeSeconds"`
QueryOwnershipType string `graphql:"queryOwnership" yaml:"queryOwnershipType" json:"queryOwnershipType"`
TriggerMode string `graphql:"triggerMode" yaml:"triggerMode" json:"triggerMode"`
QueryTimestampType string `graphql:"queryTimestampType" yaml:"queryTimestampType" json:"queryTimestampType"`
RunAsUserID string `graphql:"runAsUserId" yaml:"runAsUserId,omitempty" json:"runAsUserId,omitempty"`
}

type AggregateAlerts struct {
client *Client
}

func (c *Client) AggregateAlerts() *AggregateAlerts { return &AggregateAlerts{client: c} }

func (a *AggregateAlerts) List(viewName string) ([]*AggregateAlert, error) {
if viewName == "" {
return nil, fmt.Errorf("viewName must not be empty")
}

var query struct {
SearchDomain struct {
AggregateAlerts []humiographql.AggregateAlert `graphql:"aggregateAlerts"`
} `graphql:"searchDomain(name: $viewName)"`
}

variables := map[string]any{
"viewName": graphql.String(viewName),
}

err := a.client.Query(&query, variables)
if err != nil {
return nil, err
}

var aggregateAlerts = make([]*AggregateAlert, len(query.SearchDomain.AggregateAlerts))
for i := range query.SearchDomain.AggregateAlerts {
alert := mapHumioGraphqlAggregateAlertToAggregateAlert(query.SearchDomain.AggregateAlerts[i])
aggregateAlerts[i] = &alert
}

return aggregateAlerts, nil
}

func (a *AggregateAlerts) Update(viewName string, updatedAggregateAlert *AggregateAlert) (*AggregateAlert, error) {
if viewName == "" {
return nil, fmt.Errorf("viewName must not be empty")
}

if updatedAggregateAlert == nil {
return nil, fmt.Errorf("updatedAggregateAlert must not be nil")
}

if updatedAggregateAlert.ID == "" {
return nil, fmt.Errorf("updatedAggregateAlert must have non-empty ID")
}

var mutation struct {
humiographql.AggregateAlert `graphql:"updateAggregateAlert(input: $input)"`
}

actionNames := make([]graphql.String, len(updatedAggregateAlert.ActionNames))
for i, actionName := range updatedAggregateAlert.ActionNames {
actionNames[i] = graphql.String(actionName)
}

labels := make([]graphql.String, len(updatedAggregateAlert.Labels))
for i, label := range updatedAggregateAlert.Labels {
labels[i] = graphql.String(label)
}

updateAlert := humiographql.UpdateAggregateAlert{
ViewName: humiographql.RepoOrViewName(viewName),
ID: graphql.String(updatedAggregateAlert.ID),
Name: graphql.String(updatedAggregateAlert.Name),
Description: graphql.String(updatedAggregateAlert.Description),
QueryString: graphql.String(updatedAggregateAlert.QueryString),
SearchIntervalSeconds: humiographql.Long(updatedAggregateAlert.SearchIntervalSeconds),
ActionIdsOrNames: actionNames,
Labels: labels,
Enabled: graphql.Boolean(updatedAggregateAlert.Enabled),
RunAsUserID: graphql.String(updatedAggregateAlert.RunAsUserID),
ThrottleField: graphql.String(updatedAggregateAlert.ThrottleField),
ThrottleTimeSeconds: humiographql.Long(updatedAggregateAlert.ThrottleTimeSeconds),
TriggerMode: humiographql.TriggerMode(updatedAggregateAlert.TriggerMode),
QueryTimestampType: humiographql.QueryTimestampType(updatedAggregateAlert.QueryTimestampType),
QueryOwnershipType: humiographql.QueryOwnershipType(updatedAggregateAlert.QueryOwnershipType),
}

variables := map[string]any{
"input": updateAlert,
}

err := a.client.Mutate(&mutation, variables)
if err != nil {
return nil, err
}

aggregateAlert := mapHumioGraphqlAggregateAlertToAggregateAlert(mutation.AggregateAlert)

return &aggregateAlert, nil
}

func (a *AggregateAlerts) Create(viewName string, newAggregateAlert *AggregateAlert) (*AggregateAlert, error) {
if viewName == "" {
return nil, fmt.Errorf("viewName must not be empty")
}

if newAggregateAlert == nil {
return nil, fmt.Errorf("newAggregateAlert must not be nil")
}

var mutation struct {
humiographql.AggregateAlert `graphql:"createAggregateAlert(input: $input)"`
}

actionNames := make([]graphql.String, len(newAggregateAlert.ActionNames))
for i, actionName := range newAggregateAlert.ActionNames {
actionNames[i] = graphql.String(actionName)
}

labels := make([]graphql.String, len(newAggregateAlert.Labels))
for i, label := range newAggregateAlert.Labels {
labels[i] = graphql.String(label)
}

createAggregateAlert := humiographql.CreateAggregateAlert{
ViewName: humiographql.RepoOrViewName(viewName),
Name: graphql.String(newAggregateAlert.Name),
Description: graphql.String(newAggregateAlert.Description),
QueryString: graphql.String(newAggregateAlert.QueryString),
SearchIntervalSeconds: humiographql.Long(newAggregateAlert.SearchIntervalSeconds),
ActionIdsOrNames: actionNames,
Labels: labels,
Enabled: graphql.Boolean(newAggregateAlert.Enabled),
ThrottleField: graphql.String(newAggregateAlert.ThrottleField),
ThrottleTimeSeconds: humiographql.Long(newAggregateAlert.ThrottleTimeSeconds),
RunAsUserID: graphql.String(newAggregateAlert.RunAsUserID),
TriggerMode: humiographql.TriggerMode(newAggregateAlert.TriggerMode),
QueryTimestampType: humiographql.QueryTimestampType(newAggregateAlert.QueryTimestampType),
QueryOwnershipType: humiographql.QueryOwnershipType(newAggregateAlert.QueryOwnershipType),
}

variables := map[string]any{
"input": createAggregateAlert,
}

err := a.client.Mutate(&mutation, variables)
if err != nil {
return nil, err
}

aggregateAlert := mapHumioGraphqlAggregateAlertToAggregateAlert(mutation.AggregateAlert)

return &aggregateAlert, nil
}

func (a *AggregateAlerts) Delete(viewName, aggregateAlertID string) error {
if viewName == "" {
return fmt.Errorf("viewName must not be empty")
}

if aggregateAlertID == "" {
Comment thread
fjerlov-cs marked this conversation as resolved.
return fmt.Errorf("aggregateAlertID is empty")
}

var mutation struct {
DidDelete bool `graphql:"deleteAggregateAlert(input: { viewName: $viewName, id: $id })"`
}

variables := map[string]any{
"viewName": humiographql.RepoOrViewName(viewName),
"id": graphql.String(aggregateAlertID),
}

err := a.client.Mutate(&mutation, variables)

if !mutation.DidDelete {
return fmt.Errorf("unable to remove aggregate alert in repo/view '%s' with id '%s'", viewName, aggregateAlertID)
}

return err
}

func (a *AggregateAlerts) Get(viewName string, aggregateAlertID string) (*AggregateAlert, error) {
var query struct {
SearchDomain struct {
AggregateAlert humiographql.AggregateAlert `graphql:"aggregateAlert(id: $aggregateAlertId)"`
} `graphql:"searchDomain(name: $viewName) "`
}

if viewName == "" {
return nil, fmt.Errorf("viewName must not be empty")
}

if aggregateAlertID == "" {
return nil, fmt.Errorf("aggregateAlertID must not be empty")
}

variables := map[string]any{
"viewName": graphql.String(viewName),
"aggregateAlertId": graphql.String(aggregateAlertID),
}

err := a.client.Query(&query, variables)
if err != nil {
return nil, err
}

aggregateAlert := mapHumioGraphqlAggregateAlertToAggregateAlert(query.SearchDomain.AggregateAlert)

return &aggregateAlert, nil
}

func mapHumioGraphqlAggregateAlertToAggregateAlert(input humiographql.AggregateAlert) AggregateAlert {
var queryOwnershipType, runAsUserID string
switch input.QueryOwnership.QueryOwnershipTypeName {
case humiographql.QueryOwnershipTypeNameOrganization:
queryOwnershipType = QueryOwnershipTypeOrganization
case humiographql.QueryOwnershipTypeNameUser:
queryOwnershipType = QueryOwnershipTypeUser
runAsUserID = string(input.QueryOwnership.ID)
}

var actionNames = make([]string, len(input.Actions))
for i := range input.Actions {
actionNames[i] = string(input.Actions[i].Name)
}

var labels = make([]string, len(input.Labels))
for i := range input.Labels {
labels[i] = string(input.Labels[i])
}

return AggregateAlert{
ID: string(input.ID),
Name: string(input.Name),
Description: string(input.Description),
QueryString: string(input.QueryString),
SearchIntervalSeconds: int(input.SearchIntervalSeconds),
ActionNames: actionNames,
Labels: labels,
Enabled: bool(input.Enabled),
ThrottleField: string(input.ThrottleField),
ThrottleTimeSeconds: int(input.ThrottleTimeSeconds),
QueryOwnershipType: queryOwnershipType,
TriggerMode: string(input.TriggerMode),
QueryTimestampType: string(input.QueryTimestampType),
RunAsUserID: runAsUserID,
}
}
10 changes: 9 additions & 1 deletion api/error.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ const (
EntityTypeAlert EntityType = "alert"
EntityTypeFilterAlert EntityType = "filter-alert"
EntityTypeScheduledSearch EntityType = "scheduled-search"
EntityTypeAggregateAlert EntityType = "aggregate-alert"
)

func (e EntityType) String() string {
Expand Down Expand Up @@ -68,4 +69,11 @@ func ScheduledSearchNotFound(name string) error {
entityType: EntityTypeScheduledSearch,
key: name,
}
}
}

func AggregateAlertNotFound(name string) error {
return EntityNotFound{
entityType: EntityTypeAggregateAlert,
key: name,
}
}
7 changes: 7 additions & 0 deletions api/internal/humiographql/action.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package humiographql

import graphql "github.com/cli/shurcooL-graphql"

type Action struct {
Name graphql.String `graphql:"name"`
}
54 changes: 54 additions & 0 deletions api/internal/humiographql/aggregate-alerts.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package humiographql

import graphql "github.com/cli/shurcooL-graphql"

type AggregateAlert struct {
ID graphql.String `graphql:"id"`
Comment thread
fjerlov-cs marked this conversation as resolved.
Name graphql.String `graphql:"name"`
Comment thread
fjerlov-cs marked this conversation as resolved.
Description graphql.String `graphql:"description"`
QueryString graphql.String `graphql:"queryString"`
SearchIntervalSeconds Long `graphql:"searchIntervalSeconds"`
ThrottleTimeSeconds Long `graphql:"throttleTimeSeconds"`
ThrottleField graphql.String `graphql:"throttleField"`
Actions []Action `graphql:"actions"`
Labels []graphql.String `graphql:"labels"`
Enabled graphql.Boolean `graphql:"enabled"`
QueryOwnership QueryOwnership `graphql:"queryOwnership"`
TriggerMode TriggerMode `graphql:"triggerMode"`
QueryTimestampType QueryTimestampType `graphql:"queryTimestampType"`
}

type CreateAggregateAlert struct {
ViewName RepoOrViewName `json:"viewName"`
Name graphql.String `json:"name"`
Description graphql.String `json:"description,omitempty"`
QueryString graphql.String `json:"queryString"`
SearchIntervalSeconds Long `json:"searchIntervalSeconds"`
ThrottleTimeSeconds Long `json:"throttleTimeSeconds"`
ThrottleField graphql.String `json:"throttleField,omitempty"`
ActionIdsOrNames []graphql.String `json:"actionIdsOrNames"`
Labels []graphql.String `json:"labels"`
Enabled graphql.Boolean `json:"enabled"`
RunAsUserID graphql.String `json:"runAsUserId,omitempty"`
QueryOwnershipType QueryOwnershipType `json:"queryOwnershipType"`
TriggerMode TriggerMode `json:"triggerMode,omitempty"`
QueryTimestampType QueryTimestampType `json:"queryTimestampType"`
}

type UpdateAggregateAlert struct {
ViewName RepoOrViewName `json:"viewName"`
ID graphql.String `json:"id"`
Name graphql.String `json:"name"`
Description graphql.String `json:"description,omitempty"`
QueryString graphql.String `json:"queryString"`
SearchIntervalSeconds Long `json:"searchIntervalSeconds"`
ThrottleTimeSeconds Long `json:"throttleTimeSeconds"`
ThrottleField graphql.String `json:"throttleField,omitempty"`
ActionIdsOrNames []graphql.String `json:"actionIdsOrNames"`
Labels []graphql.String `json:"labels"`
Enabled graphql.Boolean `json:"enabled"`
RunAsUserID graphql.String `json:"runAsUserId,omitempty"`
QueryOwnershipType QueryOwnershipType `json:"queryOwnershipType"`
TriggerMode TriggerMode `json:"triggerMode"`
QueryTimestampType QueryTimestampType `json:"queryTimestampType"`
}
4 changes: 0 additions & 4 deletions api/internal/humiographql/filter-alerts.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,6 @@ type FilterAlert struct {
QueryOwnership QueryOwnership `graphql:"queryOwnership"`
}

type Action struct {
Name graphql.String `graphql:"name"`
}

type CreateFilterAlert struct {
ViewName RepoOrViewName `json:"viewName"`
Name graphql.String `json:"name"`
Expand Down
8 changes: 8 additions & 0 deletions api/internal/humiographql/query-timestamp-type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package humiographql

type QueryTimestampType string

const (
QueryTimestampTypeIngestTimestamp QueryTimestampType = "IngestTimestamp"
QueryTimestampTypeEventTimestamp QueryTimestampType = "EventTimestamp"
)
8 changes: 8 additions & 0 deletions api/internal/humiographql/trigger-mode.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package humiographql

type TriggerMode string

const (
TriggerModeCompleteMode TriggerMode = "CompleteMode"
TriggerModeImmediateMode TriggerMode = "ImmediateMode"
)
Loading