BpConfig: Delay processing of imported configurations

Solves the issue that two processes cannot import each other
This commit is contained in:
Johannes Meyer 2019-02-04 08:37:36 +01:00
parent 0194f9afe9
commit 00b88055f7
12 changed files with 85 additions and 66 deletions

View file

@ -32,6 +32,11 @@ class BpConfig
*/ */
protected $backend; protected $backend;
/**
* @var LegacyStorage
*/
protected $storage;
/** @var Metadata */ /** @var Metadata */
protected $metadata; protected $metadata;
@ -455,12 +460,12 @@ class BpConfig
public function createService($host, $service) public function createService($host, $service)
{ {
$node = new ServiceNode( $node = new ServiceNode(
$this,
(object) array( (object) array(
'hostname' => $host, 'hostname' => $host,
'service' => $service 'service' => $service
) )
); );
$node->setBpConfig($this);
$this->nodes[$host . ';' . $service] = $node; $this->nodes[$host . ';' . $service] = $node;
$this->hosts[$host] = true; $this->hosts[$host] = true;
return $node; return $node;
@ -468,7 +473,8 @@ class BpConfig
public function createHost($host) public function createHost($host)
{ {
$node = new HostNode($this, (object) array('hostname' => $host)); $node = new HostNode((object) array('hostname' => $host));
$node->setBpConfig($this);
$this->nodes[$host . ';Hoststatus'] = $node; $this->nodes[$host . ';Hoststatus'] = $node;
$this->hosts[$host] = true; $this->hosts[$host] = true;
return $node; return $node;
@ -514,11 +520,12 @@ class BpConfig
*/ */
public function createBp($name, $operator = '&') public function createBp($name, $operator = '&')
{ {
$node = new BpNode($this, (object) array( $node = new BpNode((object) array(
'name' => $name, 'name' => $name,
'operator' => $operator, 'operator' => $operator,
'child_names' => array(), 'child_names' => array(),
)); ));
$node->setBpConfig($this);
$this->addNode($name, $node); $this->addNode($name, $node);
return $node; return $node;
@ -541,18 +548,6 @@ class BpConfig
public function createImportedNode($config, $name = null) public function createImportedNode($config, $name = null)
{ {
if (! isset($this->importedConfigs[$config])) {
$import = $this->storage()->loadProcess($config);
if ($this->usesSoftStates()) {
$import->useSoftStates();
} else {
$import->useHardStates();
}
$this->importedConfigs[$config] = $import;
}
$params = (object) array('configName' => $config); $params = (object) array('configName' => $config);
if ($name !== null) { if ($name !== null) {
$params->node = $name; $params->node = $name;
@ -566,7 +561,15 @@ class BpConfig
public function getImportedConfig($name) public function getImportedConfig($name)
{ {
if (! isset($this->importedConfigs[$name])) { if (! isset($this->importedConfigs[$name])) {
throw new LogicException("Config $name not imported yet"); $import = $this->storage()->loadProcess($name);
if ($this->usesSoftStates()) {
$import->useSoftStates();
} else {
$import->useHardStates();
}
$this->importedConfigs[$name] = $import;
} }
return $this->importedConfigs[$name]; return $this->importedConfigs[$name];
@ -577,9 +580,13 @@ class BpConfig
*/ */
protected function storage() protected function storage()
{ {
return new LegacyStorage( if ($this->storage === null) {
Config::module('businessprocess')->getSection('global') $this->storage = new LegacyStorage(
); Config::module('businessprocess')->getSection('global')
);
}
return $this->storage;
} }
/** /**
@ -632,11 +639,12 @@ class BpConfig
$this->calculateAllStates(); $this->calculateAllStates();
$names = array_keys($this->getUnboundNodes()); $names = array_keys($this->getUnboundNodes());
$bp = new BpNode($this, (object) array( $bp = new BpNode((object) array(
'name' => '__unbound__', 'name' => '__unbound__',
'operator' => '&', 'operator' => '&',
'child_names' => $names 'child_names' => $names
)); ));
$bp->setBpConfig($this);
$bp->setAlias($this->translate('Unbound nodes')); $bp->setAlias($this->translate('Unbound nodes'));
return $bp; return $bp;
} }

View file

@ -48,9 +48,8 @@ class BpNode extends Node
protected $className = 'process'; protected $className = 'process';
public function __construct(BpConfig $bp, $object) public function __construct($object)
{ {
$this->bp = $bp;
$this->name = $object->name; $this->name = $object->name;
$this->operator = $object->operator; $this->operator = $object->operator;
$this->childNames = $object->child_names; $this->childNames = $object->child_names;
@ -178,7 +177,7 @@ class BpNode extends Node
{ {
if ($this->missing === null) { if ($this->missing === null) {
$exists = false; $exists = false;
$bp = $this->bp; $bp = $this->getBpConfig();
$bp->beginLoopDetection($this->name); $bp->beginLoopDetection($this->name);
foreach ($this->getChildren() as $child) { foreach ($this->getChildren() as $child) {
if (! $child->isMissing()) { if (! $child->isMissing()) {
@ -299,8 +298,8 @@ class BpNode extends Node
try { try {
$this->reCalculateState(); $this->reCalculateState();
} catch (NestingError $e) { } catch (NestingError $e) {
$this->bp->addError( $this->getBpConfig()->addError(
$this->bp->translate('Nesting error detected: %s'), $this->getBpConfig()->translate('Nesting error detected: %s'),
$e->getMessage() $e->getMessage()
); );
@ -327,7 +326,7 @@ class BpNode extends Node
*/ */
public function reCalculateState() public function reCalculateState()
{ {
$bp = $this->bp; $bp = $this->getBpConfig();
$sort_states = array(); $sort_states = array();
$lastStateChange = 0; $lastStateChange = 0;
@ -401,7 +400,7 @@ class BpNode extends Node
public function checkForLoops() public function checkForLoops()
{ {
$bp = $this->bp; $bp = $this->getBpConfig();
foreach ($this->getChildren() as $child) { foreach ($this->getChildren() as $child) {
$bp->beginLoopDetection($this->name); $bp->beginLoopDetection($this->name);
if ($child instanceof BpNode) { if ($child instanceof BpNode) {
@ -426,7 +425,7 @@ class BpNode extends Node
public function setChildNames($names) public function setChildNames($names)
{ {
if (! $this->bp->getMetadata()->isManuallyOrdered()) { if (! $this->getBpConfig()->getMetadata()->isManuallyOrdered()) {
natcasesort($names); natcasesort($names);
$names = array_values($names); $names = array_values($names);
} }
@ -451,13 +450,13 @@ class BpNode extends Node
{ {
if ($this->children === null) { if ($this->children === null) {
$this->children = array(); $this->children = array();
if (! $this->bp->getMetadata()->isManuallyOrdered()) { if (! $this->getBpConfig()->getMetadata()->isManuallyOrdered()) {
$childNames = $this->getChildNames(); $childNames = $this->getChildNames();
natcasesort($childNames); natcasesort($childNames);
$this->childNames = array_values($childNames); $this->childNames = array_values($childNames);
} }
foreach ($this->getChildNames() as $name) { foreach ($this->getChildNames() as $name) {
$this->children[$name] = $this->bp->getNode($name); $this->children[$name] = $this->getBpConfig()->getNode($name);
$this->children[$name]->addParent($this); $this->children[$name]->addParent($this);
} }
} }

View file

@ -34,11 +34,10 @@ class HostNode extends MonitoredNode
protected $icon = 'host'; protected $icon = 'host';
public function __construct(BpConfig $bp, $object) public function __construct($object)
{ {
$this->name = $object->hostname . ';Hoststatus'; $this->name = $object->hostname . ';Hoststatus';
$this->hostname = $object->hostname; $this->hostname = $object->hostname;
$this->bp = $bp;
if (isset($object->state)) { if (isset($object->state)) {
$this->setState($object->state); $this->setState($object->state);
} else { } else {
@ -62,8 +61,8 @@ class HostNode extends MonitoredNode
'host' => $this->getHostname(), 'host' => $this->getHostname(),
); );
if ($this->bp->hasBackendName()) { if ($this->getBpConfig()->hasBackendName()) {
$params['backend'] = $this->bp->getBackendName(); $params['backend'] = $this->getBpConfig()->getBackendName();
} }
return Url::fromPath('businessprocess/host/show', $params); return Url::fromPath('businessprocess/host/show', $params);

View file

@ -24,14 +24,13 @@ class ImportedNode extends BpNode
/** @var string */ /** @var string */
protected $icon = 'download'; protected $icon = 'download';
public function __construct(BpConfig $bp, $object) public function __construct(BpConfig $parentBp, $object)
{ {
$this->parentBp = $bp; $this->parentBp = $parentBp;
$this->configName = $object->configName; $this->configName = $object->configName;
$this->nodeName = $object->node; $this->nodeName = $object->node;
$importedConfig = $bp->getImportedConfig($this->configName); parent::__construct((object) [
parent::__construct($importedConfig, (object) [
'name' => '@' . $this->configName . ':' . $this->nodeName, 'name' => '@' . $this->configName . ':' . $this->nodeName,
'operator' => null, 'operator' => null,
'child_names' => null 'child_names' => null
@ -55,6 +54,15 @@ class ImportedNode extends BpNode
return $this->nodeName; return $this->nodeName;
} }
public function getBpConfig()
{
if ($this->bp === null) {
$this->bp = $this->parentBp->getImportedConfig($this->configName);
}
return $this->bp;
}
public function getAlias() public function getAlias()
{ {
if ($this->alias === null) { if ($this->alias === null) {
@ -89,7 +97,7 @@ class ImportedNode extends BpNode
{ {
if ($this->importedNode === null) { if ($this->importedNode === null) {
try { try {
$this->importedNode = $this->bp->getBpNode($this->nodeName); $this->importedNode = $this->getBpConfig()->getBpNode($this->nodeName);
} catch (Exception $e) { } catch (Exception $e) {
return $this->createFailedNode($e); return $this->createFailedNode($e);
} }
@ -106,11 +114,12 @@ class ImportedNode extends BpNode
protected function createFailedNode(Exception $e) protected function createFailedNode(Exception $e)
{ {
$this->parentBp->addError($e->getMessage()); $this->parentBp->addError($e->getMessage());
$node = new BpNode($this->bp, (object) array( $node = new BpNode((object) array(
'name' => $this->getName(), 'name' => $this->getName(),
'operator' => '&', 'operator' => '&',
'child_names' => [] 'child_names' => []
)); ));
$node->setBpConfig($this->getBpConfig());
$node->setState(2); $node->setState(2);
$node->setMissing(false) $node->setMissing(false)
->setDowntime(false) ->setDowntime(false)

View file

@ -101,7 +101,8 @@ class NodeCreateAction extends NodeAction
} else { } else {
$properties['child_names'] = array(); $properties['child_names'] = array();
} }
$node = new BpNode($config, (object) $properties); $node = new BpNode((object) $properties);
$node->setBpConfig($config);
foreach ($this->getProperties() as $key => $val) { foreach ($this->getProperties() as $key => $val) {
if ($key === 'parentName') { if ($key === 'parentName') {

View file

@ -109,7 +109,18 @@ abstract class Node
99 => 'PENDING' 99 => 'PENDING'
); );
abstract public function __construct(BpConfig $bp, $object); abstract public function __construct($object);
public function setBpConfig(BpConfig $bp)
{
$this->bp = $bp;
return $this;
}
public function getBpConfig()
{
return $this->bp;
}
public function setMissing($missing = true) public function setMissing($missing = true)
{ {
@ -341,7 +352,7 @@ abstract class Node
*/ */
public function getPaths() public function getPaths()
{ {
if ($this->bp->hasRootNode($this->getName())) { if ($this->getBpConfig()->hasRootNode($this->getName())) {
return array(array($this->getName())); return array(array($this->getName()));
} }
@ -356,14 +367,6 @@ abstract class Node
return $paths; return $paths;
} }
/**
* @return BpConfig
*/
public function getBusinessProcess()
{
return $this->bp;
}
protected function stateToSortState($state) protected function stateToSortState($state)
{ {
if (array_key_exists($state, $this->stateToSortStateMap)) { if (array_key_exists($state, $this->stateToSortStateMap)) {

View file

@ -122,7 +122,7 @@ class NodeTile extends BaseHtmlElement
$renderer = $this->renderer; $renderer = $this->renderer;
$params = [ $params = [
'config' => $node->getBusinessProcess()->getName(), 'config' => $node->getBpConfig()->getName(),
'node' => $node instanceof ImportedNode 'node' => $node instanceof ImportedNode
? $node->getNodeName() ? $node->getNodeName()
: $this->name : $this->name
@ -181,7 +181,7 @@ class NodeTile extends BaseHtmlElement
$link = Html::tag('a', ['href' => $url, 'data-base-target' => '_next'], $node->getHostname()); $link = Html::tag('a', ['href' => $url, 'data-base-target' => '_next'], $node->getHostname());
} else { } else {
$link = Html::tag('a', ['href' => $url], $node->getAlias()); $link = Html::tag('a', ['href' => $url], $node->getAlias());
if ($node->getBusinessProcess()->getName() !== $this->renderer->getBusinessProcess()->getName()) { if ($node->getBpConfig()->getName() !== $this->renderer->getBusinessProcess()->getName()) {
$link->getAttributes()->add('data-base-target', '_next'); $link->getAttributes()->add('data-base-target', '_next');
} else { } else {
$link->getAttributes()->add('data-base-target', '_self'); $link->getAttributes()->add('data-base-target', '_self');

View file

@ -169,13 +169,13 @@ class TreeRenderer extends Renderer
$div->add(Html::tag('span', ['class' => 'op'], $node->operatorHtml())); $div->add(Html::tag('span', ['class' => 'op'], $node->operatorHtml()));
} }
if (! $this->isLocked() && $node->getBusinessProcess()->getName() === $this->getBusinessProcess()->getName()) { if (! $this->isLocked() && $node->getBpConfig()->getName() === $this->getBusinessProcess()->getName()) {
$div->add($this->getActionIcons($bp, $node)); $div->add($this->getActionIcons($bp, $node));
} }
$ul = Html::tag('ul', [ $ul = Html::tag('ul', [
'class' => ['bp', 'sortable'], 'class' => ['bp', 'sortable'],
'data-sortable-disabled' => $this->isLocked() || $node->getBusinessProcess()->getName() !== $this->getBusinessProcess()->getName() ? 'true' : 'false', 'data-sortable-disabled' => $this->isLocked() || $node->getBpConfig()->getName() !== $this->getBusinessProcess()->getName() ? 'true' : 'false',
'data-sortable-invert-swap' => 'true', 'data-sortable-invert-swap' => 'true',
'data-sortable-data-id-attr' => 'id', 'data-sortable-data-id-attr' => 'id',
'data-sortable-draggable' => '.movable', 'data-sortable-draggable' => '.movable',
@ -187,7 +187,7 @@ class TreeRenderer extends Renderer
'data-csrf-token' => CsrfToken::generate(), 'data-csrf-token' => CsrfToken::generate(),
'data-action-url' => $this->getUrl() 'data-action-url' => $this->getUrl()
->overwriteParams([ ->overwriteParams([
'config' => $node->getBusinessProcess()->getName(), 'config' => $node->getBpConfig()->getName(),
'node' => $node instanceof ImportedNode 'node' => $node instanceof ImportedNode
? $node->getNodeName() ? $node->getNodeName()
: (string) $node : (string) $node
@ -222,7 +222,7 @@ class TreeRenderer extends Renderer
$link->getAttributes()->set('data-base-target', '_next'); $link->getAttributes()->set('data-base-target', '_next');
$li->add($link); $li->add($link);
if (! $this->isLocked() && $node->getBusinessProcess()->getName() === $this->getBusinessProcess()->getName()) { if (! $this->isLocked() && $node->getBpConfig()->getName() === $this->getBusinessProcess()->getName()) {
$li->add($this->getActionIcons($bp, $node)); $li->add($this->getActionIcons($bp, $node));
} }

View file

@ -14,12 +14,11 @@ class ServiceNode extends MonitoredNode
protected $icon = 'service'; protected $icon = 'service';
public function __construct(BpConfig $bp, $object) public function __construct($object)
{ {
$this->name = $object->hostname . ';' . $object->service; $this->name = $object->hostname . ';' . $object->service;
$this->hostname = $object->hostname; $this->hostname = $object->hostname;
$this->service = $object->service; $this->service = $object->service;
$this->bp = $bp;
if (isset($object->state)) { if (isset($object->state)) {
$this->setState($object->state); $this->setState($object->state);
} else { } else {
@ -49,8 +48,8 @@ class ServiceNode extends MonitoredNode
'service' => $this->getServiceDescription() 'service' => $this->getServiceDescription()
); );
if ($this->bp->hasBackendName()) { if ($this->getBpConfig()->hasBackendName()) {
$params['backend'] = $this->bp->getBackendName(); $params['backend'] = $this->getBpConfig()->getBackendName();
} }
return Url::fromPath('businessprocess/service/show', $params); return Url::fromPath('businessprocess/service/show', $params);

View file

@ -333,11 +333,12 @@ class LegacyConfigParser
$childNames[] = $val; $childNames[] = $val;
} }
$node = new BpNode($bp, (object) array( $node = new BpNode((object) array(
'name' => $name, 'name' => $name,
'operator' => $op_name, 'operator' => $op_name,
'child_names' => $childNames 'child_names' => $childNames
)); ));
$node->setBpConfig($bp);
$bp->addNode($name, $node); $bp->addNode($name, $node);
} }

View file

@ -57,9 +57,9 @@ class HostNodeTest extends BaseTestCase
protected function localhost() protected function localhost()
{ {
$bp = new BpConfig(); $bp = new BpConfig();
return new HostNode($bp, (object) array( return (new HostNode((object) array(
'hostname' => 'localhost', 'hostname' => 'localhost',
'state' => 0, 'state' => 0,
)); )))->setBpConfig($bp);
} }
} }

View file

@ -47,10 +47,10 @@ class ServiceNodeTest extends BaseTestCase
protected function pingOnLocalhost() protected function pingOnLocalhost()
{ {
$bp = new BpConfig(); $bp = new BpConfig();
return new ServiceNode($bp, (object) array( return (new ServiceNode((object) array(
'hostname' => 'localhost', 'hostname' => 'localhost',
'service' => 'ping <> pong', 'service' => 'ping <> pong',
'state' => 0, 'state' => 0,
)); )))->setBpConfig($bp);
} }
} }