From 327cb7c28cbbb5e89ddb4fa2cd835f776d7dc7c0 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Wed, 16 Jan 2019 10:25:11 +0100 Subject: [PATCH] Allow to import processes from different configurations --- application/controllers/ProcessController.php | 1 + application/forms/AddNodeForm.php | 131 ++++++++++++++---- .../Modification/NodeAddChildrenAction.php | 11 +- .../Modification/NodeCopyAction.php | 39 ++++++ .../Modification/ProcessChanges.php | 11 ++ 5 files changed, 155 insertions(+), 38 deletions(-) create mode 100644 library/Businessprocess/Modification/NodeCopyAction.php diff --git a/application/controllers/ProcessController.php b/application/controllers/ProcessController.php index 417633f..0a7bea4 100644 --- a/application/controllers/ProcessController.php +++ b/application/controllers/ProcessController.php @@ -216,6 +216,7 @@ class ProcessController extends Controller if ($action === 'add' && $canEdit) { $form = $this->loadForm('AddNode') ->setSuccessUrl(Url::fromRequest()->without('action')) + ->setStorage($this->storage()) ->setProcess($bp) ->setParentNode($node) ->setSession($this->session()) diff --git a/application/forms/AddNodeForm.php b/application/forms/AddNodeForm.php index 56b1325..872584a 100644 --- a/application/forms/AddNodeForm.php +++ b/application/forms/AddNodeForm.php @@ -6,6 +6,7 @@ use Icinga\Module\Businessprocess\BpNode; use Icinga\Module\Businessprocess\BpConfig; use Icinga\Module\Businessprocess\Modification\ProcessChanges; use Icinga\Module\Businessprocess\Web\Form\Element\Multiselect; +use Icinga\Module\Businessprocess\Storage\Storage; use Icinga\Module\Businessprocess\Web\Form\QuickForm; use Icinga\Module\Monitoring\Backend\MonitoringBackend; use Icinga\Web\Session\SessionNamespace; @@ -15,6 +16,9 @@ class AddNodeForm extends QuickForm /** @var MonitoringBackend */ protected $backend; + /** @var Storage */ + protected $storage; + /** @var BpConfig */ protected $bp; @@ -140,7 +144,7 @@ class AddNodeForm extends QuickForm return 'new-process'; } - if ($this->hasProcesses()) { + if ($this->hasProcesses() || ($this->hasParentNode() && $this->hasMoreConfigs())) { $types['process'] = $this->translate('Existing Process'); } @@ -239,33 +243,56 @@ class AddNodeForm extends QuickForm ])); } + protected function addFileElement() + { + $this->addElement('select', 'file', [ + 'label' => $this->translate('File'), + 'required' => true, + 'ignore' => true, + 'value' => $this->bp->getName(), + 'class' => 'autosubmit', + 'multiOptions' => $this->optionalEnum($this->enumConfigs()), + 'description' => $this->translate( + 'Choose a different configuration file to import its processes' + ) + ]); + } + protected function selectProcess() { - $this->addElement(new Multiselect('children', [ - 'label' => $this->translate('Process nodes'), - 'required' => true, - 'size' => 8, - 'style' => 'width: 25em', - 'multiOptions' => $this->enumProcesses(), - 'description' => $this->translate( - 'Other processes that should be part of this business process node' - ), - 'validators' => [ - ['Callback', true, [ - 'callback' => function ($value) { - if ($this->hasParentNode() && $this->parent->hasChild($value)) { - $el = $this->getElement('children'); - $el->addError(sprintf( - $this->translate('%s is already defined in this process'), - $el->getMultiOptions()[$value] - )); - } + if ($this->hasParentNode()) { + $this->addFileElement(); + } - return true; - } - ]] - ] - ])); + if (($file = $this->getSentValue('file')) || !$this->hasParentNode()) { + $this->addElement(new Multiselect('children', [ + 'label' => $this->translate('Process nodes'), + 'required' => true, + 'size' => 8, + 'style' => 'width: 25em', + 'multiOptions' => $this->enumProcesses($file), + 'description' => $this->translate( + 'Other processes that should be part of this business process node' + ), + 'validators' => [ + ['Callback', true, [ + 'callback' => function ($value) { + if ($this->hasParentNode() && $this->parent->hasChild($value)) { + $el = $this->getElement('children'); + $el->addError(sprintf( + $this->translate('%s is already defined in this process'), + $el->getMultiOptions()[$value] + )); + } + + return true; + } + ]] + ] + ])); + } else { + $this->setSubmitLabel($this->translate('Next')); + } } /** @@ -278,6 +305,16 @@ class AddNodeForm extends QuickForm return $this; } + /** + * @param Storage $storage + * @return $this + */ + public function setStorage(Storage $storage) + { + $this->storage = $storage; + return $this; + } + /** * @param BpConfig $process * @return $this @@ -368,20 +405,36 @@ class AddNodeForm extends QuickForm return count($this->enumProcesses()) > 0; } - protected function enumProcesses() + /** + * @param string $file + * @return array + */ + protected function enumProcesses($file = null) { $list = array(); $parents = array(); - if ($this->hasParentNode()) { + $differentFile = $file !== null && $file !== $this->bp->getName(); + + if (! $differentFile && $this->hasParentNode()) { $this->collectAllParents($this->parent, $parents); $parents[$this->parent->getName()] = $this->parent; } - foreach ($this->bp->getNodes() as $node) { + $bp = $this->bp; + if ($differentFile) { + $bp = $this->storage->loadProcess($file); + } + + foreach ($bp->getNodes() as $node) { if ($node instanceof BpNode && ! isset($parents[$node->getName()])) { - $list[(string) $node] = (string) $node; // display name? + $name = $node->getName(); + if ($differentFile) { + $name = '@' . $file . ':' . $name; + } + + $list[$name] = (string) $node; // display name? } } @@ -389,6 +442,17 @@ class AddNodeForm extends QuickForm return $list; } + protected function hasMoreConfigs() + { + $configs = $this->enumConfigs(); + return !empty($configs); + } + + protected function enumConfigs() + { + return $this->storage->listProcesses(); + } + /** * Collect the given node's parents recursively into the given array by their names * @@ -443,7 +507,14 @@ class AddNodeForm extends QuickForm case 'host': case 'service': case 'process': - $changes->addChildrenToNode($this->getValue('children'), $this->parent); + if ($this->hasParentNode()) { + $changes->addChildrenToNode($this->getValue('children'), $this->parent); + } else { + foreach ($this->getValue('children') as $nodeName) { + $changes->copyNode($nodeName); + } + } + break; case 'new-process': $properties = $this->getValues(); diff --git a/library/Businessprocess/Modification/NodeAddChildrenAction.php b/library/Businessprocess/Modification/NodeAddChildrenAction.php index dfd2ac2..65e8444 100644 --- a/library/Businessprocess/Modification/NodeAddChildrenAction.php +++ b/library/Businessprocess/Modification/NodeAddChildrenAction.php @@ -3,7 +3,6 @@ namespace Icinga\Module\Businessprocess\Modification; use Icinga\Module\Businessprocess\BpConfig; -use Icinga\Module\Businessprocess\BpNode; class NodeAddChildrenAction extends NodeAction { @@ -30,13 +29,6 @@ class NodeAddChildrenAction extends NodeAction */ public function applyTo(BpConfig $config) { - /** @var BpNode $node */ - if (! $this->hasNode()) { - // TODO: We end up here when defining "top nodes", but that would probably - // be a different action - return $this; - } - $node = $config->getBpNode($this->getNodeName()); foreach ($this->children as $name) { @@ -49,6 +41,9 @@ class NodeAddChildrenAction extends NodeAction } else { $config->createService($host, $service); } + } elseif ($name[0] === '@' && strpos($name, ':') !== false) { + list($configName, $nodeName) = preg_split('~:\s*~', substr($name, 1), 2); + $config->createImportedNode($configName, $nodeName); } } $node->addChild($config->getNode($name)); diff --git a/library/Businessprocess/Modification/NodeCopyAction.php b/library/Businessprocess/Modification/NodeCopyAction.php new file mode 100644 index 0000000..609d704 --- /dev/null +++ b/library/Businessprocess/Modification/NodeCopyAction.php @@ -0,0 +1,39 @@ +getNodeName(); + + if (! $config->hasBpNode($name)) { + $this->error('Process "%s" not found', $name); + } + + if ($config->hasRootNode($name)) { + $this->error('A toplevel node with name "%s" already exists', $name); + } + + return true; + } + + /** + * @param BpConfig $config + */ + public function applyTo(BpConfig $config) + { + $name = $this->getNodeName(); + $rootNodes = $config->getRootNodes(); + $config->addRootNode($name) + ->getBpNode($name) + ->setDisplay(end($rootNodes)->getDisplay() + 1); + } +} diff --git a/library/Businessprocess/Modification/ProcessChanges.php b/library/Businessprocess/Modification/ProcessChanges.php index 0293442..115b1dd 100644 --- a/library/Businessprocess/Modification/ProcessChanges.php +++ b/library/Businessprocess/Modification/ProcessChanges.php @@ -94,6 +94,17 @@ class ProcessChanges return $this->push($action); } + /** + * @param $nodeName + * @param Node|null $parent + * @return $this + */ + public function copyNode($nodeName) + { + $action = new NodeCopyAction($nodeName); + return $this->push($action, true); + } + /** * @param Node $node * @param string $parentName