pyruse/pyruse/workflow.py

74 lines
3.0 KiB
Python
Raw Normal View History

# pyruse is intended as a replacement to both fail2ban and epylog
# Copyright © 20172018 Y. Gablin
# Full licensing information in the LICENSE file, or gnu.org/licences/gpl-3.0.txt if the file is missing.
from pyruse import base, config, log, module
2017-12-15 19:36:50 +01:00
class Workflow:
def __init__(self, actions):
self._withDebug = config.Config().asMap().get("debug", False)
2017-12-15 19:36:50 +01:00
seen = {}
dangling = []
firstStep = None
for label in actions:
if not label in seen:
(entryPoint, seen, newDangling) = self._initChain(actions, label, seen, (label,))
2017-12-15 19:36:50 +01:00
if firstStep is None:
firstStep = entryPoint
elif len(dangling) > 0:
for setter in dangling:
setter(entryPoint)
dangling = newDangling
self.firstStep = firstStep
2017-12-15 19:36:50 +01:00
def _initChain(self, actions, label, seen, wholeChain):
2017-12-15 19:36:50 +01:00
dangling = []
previousSetter = None
firstStep = None
isPreviousDangling = False
isThenCalled = False
for stepNum, step in enumerate(actions[label]):
2017-12-15 19:36:50 +01:00
if isThenCalled:
break
mod = module.get(step)
obj = mod.module
if self._withDebug:
obj.setStepName(label + '[' + str(stepNum) + ']')
if mod.thenRun:
(seen, dangling) = \
self._branchToChain(
obj.setNextStep, mod.thenRun, wholeChain,
actions, seen, dangling)
isThenCalled = True
if mod.isFilter:
2017-12-15 19:36:50 +01:00
if mod.elseRun:
(seen, dangling) = \
self._branchToChain(
obj.setAltStep, mod.elseRun, wholeChain,
actions, seen, dangling)
2017-12-15 19:36:50 +01:00
else:
dangling.append(obj.setAltStep)
isPreviousDangling = mod.isFilter and not isThenCalled
2017-12-15 19:36:50 +01:00
if previousSetter:
previousSetter(obj)
else:
firstStep = obj
previousSetter = obj.setNextStep
if isPreviousDangling:
dangling.append(previousSetter)
seen[label] = firstStep if len(dangling) == 0 else None
2017-12-15 19:36:50 +01:00
return (firstStep, seen, dangling)
def _branchToChain(self, parentSetter, branchName, wholeChain, actions, seen, dangling):
if branchName in wholeChain:
raise RecursionError("Loop found in actions: %s\n" % str(wholeChain + (branchName,)))
elif branchName in seen and seen[branchName] is not None:
2017-12-15 19:36:50 +01:00
parentSetter(seen[branchName])
elif branchName in actions:
(entryPoint, seen, newDangling) = \
self._initChain(actions, branchName, seen, wholeChain + (branchName,))
2017-12-15 19:36:50 +01:00
parentSetter(entryPoint)
dangling.extend(newDangling)
else:
raise ValueError("Action chain not found: %s\n" % branchName)
return (seen, dangling)