olivetin/service/internal/executor/executor_actions.go

148 lines
3.6 KiB
Go

package executor
import (
"crypto/sha256"
"fmt"
config "github.com/OliveTin/OliveTin/internal/config"
"github.com/OliveTin/OliveTin/internal/entities"
log "github.com/sirupsen/logrus"
)
func (e *Executor) FindBindingByID(id string) *ActionBinding {
e.MapActionBindingsLock.RLock()
pair, found := e.MapActionBindings[id]
e.MapActionBindingsLock.RUnlock()
if !found {
return nil
}
return pair
}
func (e *Executor) FindBindingWithNoEntity(action *config.Action) *ActionBinding {
e.MapActionBindingsLock.RLock()
defer e.MapActionBindingsLock.RUnlock()
for _, binding := range e.MapActionBindings {
if binding.Action == action && binding.Entity == nil {
return binding
}
}
return nil
}
type RebuildActionMapRequest struct {
Cfg *config.Config
dashboardTargets *dashboardTargetIndex
}
func validateArgumentDefaults(cfg *config.Config) {
if cfg == nil {
return
}
for _, action := range cfg.Actions {
validateActionArgumentDefaults(action)
}
}
func validateActionArgumentDefaults(action *config.Action) {
if action == nil {
return
}
for i := range action.Arguments {
validateArgumentDefault(action, &action.Arguments[i])
}
}
func validateArgumentDefault(action *config.Action, arg *config.ActionArgument) {
if arg.Default == "" {
return
}
if err := ValidateArgument(arg, arg.Default, action); err != nil {
log.WithFields(log.Fields{
"actionTitle": action.Title,
"argName": arg.Name,
"default": arg.Default,
"error": err,
}).Warn("Argument default value failed validation")
}
}
func (e *Executor) RebuildActionMap() {
validateArgumentDefaults(e.Cfg)
e.MapActionBindingsLock.Lock()
clear(e.MapActionBindings)
req := &RebuildActionMapRequest{
Cfg: e.Cfg,
dashboardTargets: buildDashboardTargetIndex(e.Cfg),
}
for configOrder, action := range e.Cfg.Actions {
if action.Entity != "" {
registerActionsFromEntities(e, configOrder, action.Entity, action, req)
} else {
registerAction(e, configOrder, action, req)
}
}
e.MapActionBindingsLock.Unlock()
for _, l := range e.copyListeners() {
l.OnActionMapRebuilt()
}
}
func registerAction(e *Executor, configOrder int, action *config.Action, req *RebuildActionMapRequest) {
bindingId := generateActionBindingId(action, "")
e.MapActionBindings[bindingId] = &ActionBinding{
ID: bindingId,
Action: action,
Entity: nil,
ConfigOrder: configOrder,
OnDashboards: resolveOnDashboards(req.dashboardTargets, action.Title, ""),
}
}
func registerActionsFromEntities(e *Executor, configOrder int, entityTitle string, tpl *config.Action, req *RebuildActionMapRequest) {
for _, ent := range entities.GetEntityInstancesOrdered(entityTitle) {
registerActionFromEntity(e, configOrder, tpl, ent, req)
}
}
func registerActionFromEntity(e *Executor, configOrder int, tpl *config.Action, ent *entities.Entity, req *RebuildActionMapRequest) {
virtualActionId := generateActionBindingId(tpl, ent.UniqueKey)
e.MapActionBindings[virtualActionId] = &ActionBinding{
ID: virtualActionId,
Action: tpl,
Entity: ent,
ConfigOrder: configOrder,
OnDashboards: resolveOnDashboards(req.dashboardTargets, tpl.Title, ent.UniqueKey),
}
}
func generateActionBindingId(action *config.Action, entityPrefix string) string {
if action.ID != "" && entityPrefix == "" {
return action.ID
}
h := sha256.New()
if entityPrefix == "" {
h.Write([]byte(action.Title))
} else {
// Include the entity data to make each entity instance unique
h.Write([]byte(action.Title + "." + entityPrefix))
}
return fmt.Sprintf("%x", h.Sum(nil))
}