executor_actions.go 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package executor
  2. import (
  3. "crypto/sha256"
  4. "fmt"
  5. config "github.com/OliveTin/OliveTin/internal/config"
  6. "github.com/OliveTin/OliveTin/internal/entities"
  7. log "github.com/sirupsen/logrus"
  8. )
  9. func (e *Executor) FindBindingByID(id string) *ActionBinding {
  10. e.MapActionBindingsLock.RLock()
  11. pair, found := e.MapActionBindings[id]
  12. e.MapActionBindingsLock.RUnlock()
  13. if !found {
  14. return nil
  15. }
  16. return pair
  17. }
  18. func (e *Executor) FindBindingWithNoEntity(action *config.Action) *ActionBinding {
  19. e.MapActionBindingsLock.RLock()
  20. defer e.MapActionBindingsLock.RUnlock()
  21. for _, binding := range e.MapActionBindings {
  22. if binding.Action == action && binding.Entity == nil {
  23. return binding
  24. }
  25. }
  26. return nil
  27. }
  28. type RebuildActionMapRequest struct {
  29. Cfg *config.Config
  30. dashboardTargets *dashboardTargetIndex
  31. }
  32. func validateArgumentDefaults(cfg *config.Config) {
  33. if cfg == nil {
  34. return
  35. }
  36. for _, action := range cfg.Actions {
  37. validateActionArgumentDefaults(action)
  38. }
  39. }
  40. func validateActionArgumentDefaults(action *config.Action) {
  41. if action == nil {
  42. return
  43. }
  44. for i := range action.Arguments {
  45. validateArgumentDefault(action, &action.Arguments[i])
  46. }
  47. }
  48. func validateArgumentDefault(action *config.Action, arg *config.ActionArgument) {
  49. if arg.Default == "" {
  50. return
  51. }
  52. if err := ValidateArgument(arg, arg.Default, action); err != nil {
  53. log.WithFields(log.Fields{
  54. "actionTitle": action.Title,
  55. "argName": arg.Name,
  56. "default": arg.Default,
  57. "error": err,
  58. }).Warn("Argument default value failed validation")
  59. }
  60. }
  61. func (e *Executor) RebuildActionMap() {
  62. validateArgumentDefaults(e.Cfg)
  63. e.MapActionBindingsLock.Lock()
  64. clear(e.MapActionBindings)
  65. req := &RebuildActionMapRequest{
  66. Cfg: e.Cfg,
  67. dashboardTargets: buildDashboardTargetIndex(e.Cfg),
  68. }
  69. for configOrder, action := range e.Cfg.Actions {
  70. if action.Entity != "" {
  71. registerActionsFromEntities(e, configOrder, action.Entity, action, req)
  72. } else {
  73. registerAction(e, configOrder, action, req)
  74. }
  75. }
  76. e.MapActionBindingsLock.Unlock()
  77. for _, l := range e.copyListeners() {
  78. l.OnActionMapRebuilt()
  79. }
  80. }
  81. func registerAction(e *Executor, configOrder int, action *config.Action, req *RebuildActionMapRequest) {
  82. bindingId := generateActionBindingId(action, "")
  83. e.MapActionBindings[bindingId] = &ActionBinding{
  84. ID: bindingId,
  85. Action: action,
  86. Entity: nil,
  87. ConfigOrder: configOrder,
  88. OnDashboards: resolveOnDashboards(req.dashboardTargets, action.Title, ""),
  89. }
  90. }
  91. func registerActionsFromEntities(e *Executor, configOrder int, entityTitle string, tpl *config.Action, req *RebuildActionMapRequest) {
  92. for _, ent := range entities.GetEntityInstancesOrdered(entityTitle) {
  93. registerActionFromEntity(e, configOrder, tpl, ent, req)
  94. }
  95. }
  96. func registerActionFromEntity(e *Executor, configOrder int, tpl *config.Action, ent *entities.Entity, req *RebuildActionMapRequest) {
  97. virtualActionId := generateActionBindingId(tpl, ent.UniqueKey)
  98. e.MapActionBindings[virtualActionId] = &ActionBinding{
  99. ID: virtualActionId,
  100. Action: tpl,
  101. Entity: ent,
  102. ConfigOrder: configOrder,
  103. OnDashboards: resolveOnDashboards(req.dashboardTargets, tpl.Title, ent.UniqueKey),
  104. }
  105. }
  106. func generateActionBindingId(action *config.Action, entityPrefix string) string {
  107. if action.ID != "" && entityPrefix == "" {
  108. return action.ID
  109. }
  110. h := sha256.New()
  111. if entityPrefix == "" {
  112. h.Write([]byte(action.Title))
  113. } else {
  114. // Include the entity data to make each entity instance unique
  115. h.Write([]byte(action.Title + "." + entityPrefix))
  116. }
  117. return fmt.Sprintf("%x", h.Sum(nil))
  118. }