mirror of
https://github.com/OliveTin/OliveTin
synced 2026-08-26 12:36:30 +00:00
166 lines
4.2 KiB
Go
166 lines
4.2 KiB
Go
package executor
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"fmt"
|
|
"strings"
|
|
|
|
"github.com/OliveTin/OliveTin/internal/config"
|
|
"github.com/OliveTin/OliveTin/internal/configcheck"
|
|
"github.com/OliveTin/OliveTin/internal/configissues"
|
|
"github.com/OliveTin/OliveTin/internal/entities"
|
|
)
|
|
|
|
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) []configissues.Issue {
|
|
if cfg == nil {
|
|
return nil
|
|
}
|
|
out := make([]configissues.Issue, 0)
|
|
for _, action := range cfg.Actions {
|
|
out = append(out, validateActionArgumentDefaults(action)...)
|
|
}
|
|
return out
|
|
}
|
|
|
|
func validateActionArgumentDefaults(action *config.Action) []configissues.Issue {
|
|
if action == nil {
|
|
return nil
|
|
}
|
|
out := make([]configissues.Issue, 0)
|
|
for i := range action.Arguments {
|
|
if issue := validateArgumentDefault(action, &action.Arguments[i]); issue != nil {
|
|
out = append(out, *issue)
|
|
}
|
|
}
|
|
return out
|
|
}
|
|
|
|
func validateArgumentDefault(action *config.Action, arg *config.ActionArgument) *configissues.Issue {
|
|
if arg.Default == "" {
|
|
return nil
|
|
}
|
|
if strings.Contains(arg.Default, "{{") {
|
|
return nil
|
|
}
|
|
if err := ValidateArgument(arg, arg.Default, action); err != nil {
|
|
return &configissues.Issue{
|
|
Severity: configissues.SeverityWarning,
|
|
Code: configissues.CodeArgDefaultInvalid,
|
|
Message: fmt.Sprintf("Argument default value failed validation: %v", err),
|
|
ActionID: action.ID,
|
|
ActionTitle: action.Title,
|
|
ArgumentName: arg.Name,
|
|
Source: arg.Default,
|
|
ConfigFile: action.SourceFile,
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (e *Executor) RebuildActionMap() {
|
|
defaultIssues := 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()
|
|
|
|
configcheck.Rebuild(e.Cfg, defaultIssues...)
|
|
|
|
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))
|
|
}
|