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)) }