Skip to content

Commit

Permalink
DependencyChecker: new implemenation
Browse files Browse the repository at this point in the history
This is now also able to give help for web 2.9.x

fixes #2354
fixes #2350
  • Loading branch information
Thomas-Gelf committed Jul 13, 2021
1 parent 44ca889 commit 6badc53
Show file tree
Hide file tree
Showing 9 changed files with 447 additions and 100 deletions.
37 changes: 9 additions & 28 deletions application/controllers/PhperrorController.php
Expand Up @@ -3,7 +3,8 @@
namespace Icinga\Module\Director\Controllers;

use Icinga\Application\Icinga;
use Icinga\Application\Modules\Manager;
use Icinga\Module\Director\Application\DependencyChecker;
use Icinga\Module\Director\Web\Table\Dependency\DependencyInfoTable;
use Icinga\Web\Controller;

class PhperrorController extends Controller
Expand All @@ -24,39 +25,19 @@ public function errorAction()

public function dependenciesAction()
{
$dependencies = $this->view->dependencies = $this->Module()->getDependencies();
$modules = $this->view->modules = Icinga::app()->getModuleManager();
// Hint: we're duplicating some code here
$satisfied = true;
foreach ($dependencies as $module => $required) {
/** @var Manager $this ->modules */
if ($modules->hasEnabled($module)) {
$installed = $modules->getModule($module, false)->getVersion();
$installed = \ltrim($installed, 'v'); // v0.6.0 VS 0.6.0
if (\preg_match('/^([<>=]+)\s*v?(\d+\.\d+\.\d+)$/', $required, $match)) {
$operator = $match[1];
$vRequired = $match[2];
if (\version_compare($installed, $vRequired, $operator)) {
continue;
}
}
}
$satisfied = false;
}

if ($satisfied) {
$checker = new DependencyChecker(Icinga::app());
if ($checker->satisfiesDependencies($this->Module())) {
$this->redirectNow('director');
}

$this->setAutorefreshInterval(15);
$this->getTabs()->add('error', array(
$this->getTabs()->add('error', [
'label' => $this->translate('Error'),
'url' => $this->getRequest()->getUrl()
))->activate('error');
$msg = $this->translate(
])->activate('error');
$this->view->title = $this->translate('Unsatisfied dependencies');
$this->view->table = (new DependencyInfoTable($checker, $this->Module()))->render();
$this->view->message = $this->translate(
"Icinga Director depends on the following modules, please install/upgrade as required"
);
$this->view->title = $this->translate('Unsatisfied dependencies');
$this->view->message = sprintf($msg, PHP_VERSION);
}
}
59 changes: 1 addition & 58 deletions application/views/scripts/phperror/dependencies.phtml
Expand Up @@ -10,62 +10,5 @@ use Icinga\Application\Modules\Manager;

<div class="content">
<p class="legacy-error"><?= $this->escape($this->message) ?></p>
<table class="common-table table-row-selectable">
<thead>
<tr>
<th><?= $this->translate('Module name') ?></th>
<th><?= $this->translate('Required') ?></th>
<th><?= $this->translate('Installed') ?></th>
</tr>
</thead>
<tbody data-base-target="_next">
<?php

foreach ($this->dependencies as $module => $required) {
/** @var Manager $this->modules */
if ($modules->hasEnabled($module)) {
$installed = $modules->getModule($module, false)->getVersion();
$installed = \ltrim($installed, 'v'); // v0.6.0 VS 0.6.0
if (\preg_match('/^([<>=]+)\s*v?(\d+\.\d+\.\d+)$/', $required, $match)) {
$operator = $match[1];
$vRequired = $match[2];
if (\version_compare($installed, $vRequired, $operator)) {
$icon = 'ok';
} else {
$icon = 'cancel';
}
} else {
$icon = 'cancel';
}
$link = $this->qlink(
$module,
'config/module',
['name' => $module],
['class' => "icon-$icon"]
);
} elseif ($modules->hasInstalled($module)) {
$installed = $this->translate('disabled');
$link = $this->qlink($module, 'config/module', ['name' => $module], ['class' => 'icon-cancel']);
} else {
$installed = $this->translate('missing');
$link = sprintf(
'<a href="#" class="icon-cancel">%s</a> (<a href="https://github.com/Icinga/icingaweb2-module-%s"'
. ' target="_blank" rel="noreferrer">%s</a>)',
$this->escape($module),
$this->escape($module),
$this->translate('more')
);
}

\printf(
'<tr><td>%s</a></td><td>%s</td><td>%s</td></tr>',
$link,
$this->escape($required),
$this->escape($installed)
);
}

?>
</tbody>
</table>
<?= $this->table ?>
</div>
1 change: 1 addition & 0 deletions doc/82-Changelog.md
Expand Up @@ -48,6 +48,7 @@ next patch release (will be 1.8.1)
* FIX: show "deactivated" services as such also for read-only users (#2344)
* FIX: Overrides for Services belonging to Sets on root Host Templates (#2333)
* FIX: show no header tabs for search result in web 2.8+ (#2141)
* FIX: show and link dependencies for web 2.9+ (#2354)

### Icinga Configuration
* FIX: rare race condition, where generated config might miss some files (#2351)
Expand Down
113 changes: 113 additions & 0 deletions library/Director/Application/Dependency.php
@@ -0,0 +1,113 @@
<?php

namespace Icinga\Module\Director\Application;

class Dependency
{
/** @var string */
protected $name;

/** @var string|null */
protected $installedVersion;

/** @var bool|null */
protected $enabled;

/** @var string */
protected $operator;

/** @var string */
protected $requiredVersion;

/** @var string */
protected $requirement;

/**
* Dependency constructor.
* @param string $name Usually a module name
* @param string $requirement e.g. >=1.7.0
* @param string $installedVersion
* @param bool $enabled
*/
public function __construct($name, $requirement, $installedVersion = null, $enabled = null)
{
$this->name = $name;
$this->setRequirement($requirement);
if ($installedVersion !== null) {
$this->setInstalledVersion($installedVersion);
}
if ($enabled !== null) {
$this->setEnabled($enabled);
}
}

public function setRequirement($requirement)
{
if (preg_match('/^([<>=]+)\s*v?(\d+\.\d+\.\d+)$/', $requirement, $match)) {
$this->operator = $match[1];
$this->requiredVersion = $match[2];
$this->requirement = $requirement;
} else {
throw new \InvalidArgumentException("'$requirement' is not a valid version constraint");
}
}

/**
* @return bool
*/
public function isInstalled()
{
return $this->installedVersion !== null;
}

/**
* @return string|null
*/
public function getInstalledVersion()
{
return $this->installedVersion;
}

/**
* @param string $version
*/
public function setInstalledVersion($version)
{
$this->installedVersion = ltrim($version, 'v'); // v0.6.0 VS 0.6.0
}

/**
* @return bool
*/
public function isEnabled()
{
return $this->enabled === true;
}

/**
* @param bool $enabled
*/
public function setEnabled($enabled = true)
{
$this->enabled = $enabled;
}

public function isSatisfied()
{
if (! $this->isInstalled() || ! $this->isEnabled()) {
return false;
}

return version_compare($this->installedVersion, $this->requiredVersion, $this->operator);
}

public function getName()
{
return $this->name;
}

public function getRequirement()
{
return $this->requirement;
}
}
73 changes: 73 additions & 0 deletions library/Director/Application/DependencyChecker.php
@@ -0,0 +1,73 @@
<?php

namespace Icinga\Module\Director\Application;

use Icinga\Application\ApplicationBootstrap;
use Icinga\Application\Modules\Module;
use Icinga\Application\Version;

class DependencyChecker
{
/** @var ApplicationBootstrap */
protected $app;

/** @var \Icinga\Application\Modules\Manager */
protected $modules;

public function __construct(ApplicationBootstrap $app)
{
$this->app = $app;
$this->modules = $app->getModuleManager();
}

/**
* @param Module $module
* @return Dependency[]
*/
public function getDependencies(Module $module)
{
$dependencies = [];
$isV290 = version_compare(Version::VERSION, '2.9.0', '>=');
foreach ($module->getDependencies() as $moduleName => $required) {
if ($isV290 && in_array($moduleName, ['ipl', 'reactbundle'], true)) {
continue;
}
$dependency = new Dependency($moduleName, $required);
$dependency->setEnabled($this->modules->hasEnabled($moduleName));
if ($this->modules->hasInstalled($moduleName)) {
$dependency->setInstalledVersion($this->modules->getModule($moduleName, false)->getVersion());
}
$dependencies[] = $dependency;
}
if ($isV290) {
$libs = $this->app->getLibraries();
foreach ($module->getRequiredLibraries() as $libraryName => $required) {
$dependency = new Dependency($libraryName, $required);
if ($libs->has($libraryName)) {
$dependency->setInstalledVersion($libs->get($libraryName)->getVersion());
$dependency->setEnabled();
}
$dependencies[] = $dependency;
}
}

return $dependencies;
}

// if (version_compare(Version::VERSION, '2.9.0', 'ge')) {
// }
/**
* @param Module $module
* @return bool
*/
public function satisfiesDependencies(Module $module)
{
foreach ($this->getDependencies($module) as $dependency) {
if (! $dependency->isSatisfied()) {
return false;
}
}

return true;
}
}

0 comments on commit 6badc53

Please sign in to comment.