Merge branch 'next'

This commit is contained in:
Thomas Gelf 2019-09-11 22:44:27 +02:00
commit dbc4699042
22 changed files with 256 additions and 275 deletions

View File

@ -1,246 +0,0 @@
<?php
namespace Icinga\Module\Director\Clicommands;
use Icinga\Application\Logger;
use Icinga\Cli\Command;
use Icinga\Module\Director\Test\TestSuiteLint;
use Icinga\Module\Director\Test\TestSuiteStyle;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
class TestCommand extends Command
{
/**
* Default arguments and options for PHP_CodeSniffer
*
* @var array
*/
protected $phpcsDefaultParams = array(
'-p',
'--standard=PSR2',
'--extensions=php',
'--encoding=utf-8'
);
public function lintAction()
{
$test = new TestSuiteLint();
$test->run();
if ($test->hasFailures()) {
Logger::error('Lint check failed');
exit(1);
} else {
Logger::info('Lint check succeeded');
exit(0);
}
}
/**
* Run all unit-test suites
*
* This command runs the unit- and regression-tests of icingaweb and installed modules.
*
* USAGE
*
* icingacli test php unit [options]
*
* OPTIONS
*
* --verbose Be more verbose.
* --build Enable reporting.
* --include Pattern to use for including files/test cases.
*
* EXAMPLES
*
* icingacli test php unit --verbose
* icingacli test php unit --build
* icingacli test php unit --include=*SpecialTest
*/
public function phpAction()
{
$basedir = $this->getBaseDir();
$build = $this->params->shift('build');
$include = $this->params->shift('include');
$phpUnit = exec('which phpunit');
if (!file_exists($phpUnit)) {
$this->fail('PHPUnit not found. Please install PHPUnit to be able to run the unit-test suites.');
}
$options = array(
'--bootstrap' => $basedir . '/test/bootstrap.php'
);
if ($this->isVerbose) {
$options[] = '--verbose --testdox';
}
if ($build) {
$reportPath = $this->setupAndReturnReportDirectory();
$options[] = '--verbose';
$options[] = '--log-junit';
$options[] = $reportPath . '/phpunit_results.xml';
$options[] = '--coverage-html';
$options[] = $reportPath . '/php_html_coverage';
}
if ($include !== null) {
$options[] = '--filter';
$options[] = $include;
}
chdir(realpath(__DIR__ . '/../..'));
$command = $phpUnit . ' ' . join(' ', array_merge($options, $this->params->getAllStandalone()));
if ($this->isVerbose) {
$res = `$command`;
foreach (preg_split('/\n/', $res) as $line) {
if (preg_match('~\s+\[([x\s])\]\s~', $line, $m)) {
if ($m[1] === 'x') {
echo $this->screen->colorize($line, 'green') . "\n";
} else {
echo $this->screen->colorize($line, 'red') . "\n";
}
} else {
echo $line . "\n";
}
}
} else {
passthru($command);
}
}
/**
* Run code-style checks
*
* This command checks whether icingaweb and installed modules match the PSR-2 coding standard.
*
* USAGE
*
* icingacli test php style [options]
*
* OPTIONS
*
* --verbose Be more verbose.
* --build Enable reporting.
* --include Include only specific files. (Can be supplied multiple times.)
* --exclude Pattern to use for excluding files. (Can be supplied multiple times.)
*
* EXAMPLES
*
* icingacli test php style --verbose
* icingacli test php style --build
* icingacli test php style --include=path/to/your/file
* icingacli test php style --exclude=*someFile* --exclude=someOtherFile*
*/
public function styleAction()
{
// passthru(
// 'phpcs -p --standard=PSR2 --extensions=php --encoding=utf-8 -w -s
// --report-checkstyle=/tmp/style/bla library/Director/ application/
// run.php configuration.php'
// );
$test = new TestSuiteStyle();
$test->run();
return;
// TODO: obsolete:
if ($test->hasFailures()) {
$this->fail('Lint check failed');
} else {
Logger::info('Lint check succeeded');
}
$out = TestRunner::newTempFile();
$check = array(
'library/Director/',
'application/',
'configuration.php',
'run.php',
);
$cmd = sprintf(
"phpcs -p --standard=PSR2 --extensions=php --encoding=utf-8 -w -s --report-checkstyle=%s '%s'",
$out,
implode("' '", $check)
);
// TODO: Debug only:
`$cmd`;
echo $cmd . "\n";
echo $out ."\n";
echo file_get_contents($out);
unlink($out);
exit;
$build = $this->params->shift('build');
$include = (array) $this->params->shift('include', array());
$exclude = (array) $this->params->shift('exclude', array());
$phpcs = exec('which phpcs');
if (!file_exists($phpcs)) {
$this->fail(
'PHP_CodeSniffer not found. Please install PHP_CodeSniffer to be able to run code style tests.'
);
}
$options = array();
if ($this->isVerbose) {
$options[] = '-v';
}
if ($build) {
$options[] = '--report-checkstyle=' . $this->setupAndReturnReportDirectory();
}
if (!empty($exclude)) {
$options[] = '--ignore=' . join(',', $exclude);
}
$arguments = array_filter(
array_map(
function ($p) {
return realpath($p);
},
$include
)
);
if (empty($arguments)) {
$arguments = array(
realpath(__DIR__ . '/../../../../application'),
realpath(__DIR__ . '/../../../../library/Icinga')
);
}
chdir(realpath(__DIR__ . '/../..'));
passthru(
$phpcs . ' ' . join(
' ',
array_merge(
$options,
$this->phpcsDefaultParams,
$arguments,
$this->params->getAllStandalone()
)
)
);
}
protected function getBaseDir()
{
return dirname(dirname(__DIR__));
}
/**
* Setup the directory where to put report files and return its path
*
* @return string
*/
protected function setupAndReturnReportDirectory()
{
$path = '/tmp/test-devel';
if (!is_dir($path) && !@mkdir($path, 0755, true)) {
$this->fail("Could not create directory: $path");
}
return $path;
}
}

View File

@ -2,6 +2,7 @@
namespace Icinga\Module\Director\Controllers;
use Icinga\Application\Icinga;
use Icinga\Web\Controller;
class PhperrorController extends Controller
@ -19,4 +20,20 @@ class PhperrorController extends Controller
$this->view->title = $this->translate('Unsatisfied dependencies');
$this->view->message = sprintf($msg, PHP_VERSION);
}
public function dependenciesAction()
{
$this->setAutorefreshInterval(15);
$this->view->dependencies = $this->Module()->getDependencies();
$this->view->modules = Icinga::app()->getModuleManager();
$this->getTabs()->add('error', array(
'label' => $this->translate('Error'),
'url' => $this->getRequest()->getUrl()
))->activate('error');
$msg = $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);
}
}

View File

@ -2,7 +2,7 @@
namespace Icinga\Module\Director\Controllers;
use dipl\Web\Widget\UnorderedList;
use Icinga\Module\Director\Web\Widget\UnorderedList;
use Icinga\Module\Director\ConfigDiff;
use Icinga\Module\Director\Db\Cache\PrefetchCache;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;

View File

@ -2,6 +2,7 @@
namespace Icinga\Module\Director\Forms;
use gipfl\IcingaWeb2\Link;
use Icinga\Module\Director\Web\Form\DirectorObjectForm;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaService;

View File

@ -1,7 +1,7 @@
<?php
use dipl\Html\Html;
use dipl\Html\HtmlDocument;
use ipl\Html\Html;
use ipl\Html\HtmlDocument;
/**
* Please see StoredPassword (the Form Element) for related documentation

View File

@ -0,0 +1,71 @@
<?php
use Icinga\Application\Modules\Manager;
?>
<div class="controls">
<?= $this->tabs ?>
<h1><?= $this->escape($this->title) ?></h1>
</div>
<div class="content">
<p class="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>
</div>

View File

@ -19,9 +19,9 @@ Requirements
* Icinga Web 2 (&gt;= 2.6.0). All versions since 2.2 should also work fine, but
might show smaller UI bugs and are not actively tested
* The following Icinga modules must be installed and enabled:
* [ipl](https://github.com/Icinga/icingaweb2-module-ipl)
* [incubator](https://github.com/Icinga/icingaweb2-module-incubator)
* [reactbundle](https://github.com/Icinga/icingaweb2-module-reactbundle)
* [ipl](https://github.com/Icinga/icingaweb2-module-ipl) (>=0.3.0)
* [incubator](https://github.com/Icinga/icingaweb2-module-incubator) (>=0.3.0)
* [reactbundle](https://github.com/Icinga/icingaweb2-module-reactbundle) (>=0.6.0)
* A database, MySQL (&gt;= 5.1) or PostgreSQL (&gt;= 9.1). MariaDB and other
MySQL forks are also fine. Mentioned versions are the required minimum,
for MySQL we suggest using at least 5.5.3, for PostgreSQL 9.4.

View File

@ -16,6 +16,7 @@ you will be told so in your frontend.
Please read more about:
* [Database Backup](#backup-first)
* [Upgrading to 1.7.x](#upgrade-to-1.7.x)
* [Upgrading to 1.6.x](#upgrade-to-1.6.x)
* [Upgrading to 1.5.x](#upgrade-to-1.5.x)
* [Upgrading to 1.4.x](#upgrade-to-1.4.x)
@ -38,6 +39,23 @@ use the tools provided by your database backend, like `mysqldump` or `pg_dump`.
Restoring from a backup is trivial, and Director will always be able to apply
pending database migrations to an imported old database snapshot.
<a name="upgrade-to-1.7.x"></a>Upgrading to 1.7.x
-------------------------------------------------
Since v1.7.0 Icinga Director requires at least PHP 5.6. Also, this version
introduces new dependencies. Please make sure that the following Icinga Web 2
modules have been installed and enabled:
* [ipl](https://github.com/Icinga/icingaweb2-module-ipl) (>=0.3.0)
* [incubator](https://github.com/Icinga/icingaweb2-module-incubator) (>=0.3.0)
* [reactbundle](https://github.com/Icinga/icingaweb2-module-reactbundle) (>=0.6.0)
Apart from this, in case you are running 1.6.x or any GIT master since then,
all you need is to replace the Director module folder with the new one. Or to
run `git checkout v1.7.x` in case you installed Director from GIT.
As always, you'll then be prompted to apply pending Database Migrations.
<a name="upgrade-to-1.6.x"></a>Upgrading to 1.6.x
-------------------------------------------------

View File

@ -2359,12 +2359,7 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
);
}
$str = sprintf(
"define %s {\n$name",
$type,
$name
);
$str = "define $type {\n$name";
if ($this->isTemplate()) {
$str .= c1::renderKeyValue('register', '0');
}

View File

@ -11,9 +11,7 @@ abstract class IcingaObjectField extends DbObject
*
* @param Filter|string $filter
*
* @throws ProgrammingError
*
* @return self
* @return $this
* @codingStandardsIgnoreStart
*/
protected function setVar_filter($value)

View File

@ -2,7 +2,7 @@
namespace Icinga\Module\Director\Objects;
class IcingaServiceAssignment extends IcingaObject
class IcingaServiceSetAssignment extends IcingaObject
{
protected $table = 'icinga_service_set_assignment';

View File

@ -12,11 +12,11 @@ use Icinga\Module\Director\Web\Table\ObjectsTable;
use Icinga\Module\Director\Web\Table\TemplatesTable;
use Icinga\Module\Director\Web\Table\TemplateUsageTable;
use Icinga\Module\Director\Web\Tabs\ObjectTabs;
use dipl\Html\FormattedString;
use dipl\Html\Html;
use dipl\Html\Link;
use dipl\Web\CompatController;
use dipl\Web\Widget\UnorderedList;
use Icinga\Module\Director\Web\Widget\UnorderedList;
use ipl\Html\FormattedString;
use ipl\Html\Html;
use gipfl\IcingaWeb2\Link;
use gipfl\IcingaWeb2\CompatController;
abstract class TemplateController extends CompatController
{

View File

@ -170,6 +170,11 @@ class ObjectsTable extends ZfQueryBasedTable
return $tr;
}
protected function getRowClasses($row)
{
return [];
}
protected function applyObjectTypeFilter(ZfSelect $query)
{
return $query->where(

View File

@ -0,0 +1,40 @@
<?php
namespace Icinga\Module\Director\Web\Widget;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\HtmlElement;
class AbstractList extends BaseHtmlElement
{
protected $contentSeparator = "\n";
/**
* AbstractList constructor.
* @param array $items
* @param null $attributes
*/
public function __construct(array $items = [], $attributes = null)
{
foreach ($items as $item) {
$this->addItem($item);
}
if ($attributes !== null) {
$this->addAttributes($attributes);
}
}
/**
* @param Html|array|string $content
* @param Attributes|array $attributes
*
* @return $this
*/
public function addItem($content, $attributes = null)
{
return $this->add(HtmlElement::create('li', $attributes, $content));
}
}

View File

@ -0,0 +1,26 @@
<?php
namespace Icinga\Module\Director\Web\Widget;
use ipl\Html\Attributes;
use ipl\Html\BaseHtmlElement;
use ipl\Html\Html;
use ipl\Html\ValidHtml;
class ListItem extends BaseHtmlElement
{
protected $contentSeparator = "\n";
/**
* @param ValidHtml|array|string $content
* @param Attributes|array $attributes
*
* @return $this
*/
public function addItem($content, $attributes = null)
{
return $this->add(
Html::tag('li', $attributes, $content)
);
}
}

View File

@ -0,0 +1,8 @@
<?php
namespace Icinga\Module\Director\Web\Widget;
class OrderedList extends AbstractList
{
protected $tag = 'ol';
}

View File

@ -0,0 +1,8 @@
<?php
namespace Icinga\Module\Director\Web\Widget;
class UnorderedList extends AbstractList
{
protected $tag = 'ul';
}

View File

@ -1,6 +1,6 @@
Name: Icinga Director
Version: master
Depends: monitoring
Depends: reactbundle (>=0.6.0), ipl (>=0.3.0), incubator (>=0.3.0)
Description: Director - Config tool for Icinga 2
Icinga Director is a configuration tool that has been designed to make
Icinga 2 configuration easy and understandable.

23
run-missingdeps.php Normal file
View File

@ -0,0 +1,23 @@
<?php
use Icinga\Application\Icinga;
use Icinga\Exception\IcingaException;
use Icinga\Web\Url;
if (Icinga::app()->isCli()) {
throw new IcingaException(
"Missing dependencies, please check "
);
} else {
$request = Icinga::app()->getRequest();
$path = $request->getPathInfo();
if (! preg_match('#^/director#', $path)) {
return;
}
if (preg_match('#^/director/phperror/dependencies#', $path)) {
return;
}
header('Location: ' . Url::fromPath('director/phperror/dependencies'));
exit;
}

17
run.php
View File

@ -65,3 +65,20 @@ $this->provideHook('cube/Actions', 'CubeLinks');
require_once __DIR__ . '/library/vendor/ipl/Loader/CompatLoader.php';
CompatLoader::delegateLoadingToIcingaWeb($this->app);
$modules = $this->app->getModuleManager();
foreach ($this->getDependencies() as $module => $required) {
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;
}
}
include __DIR__ . '/run-missingdeps.php';
return;
}
}

View File

@ -32,7 +32,7 @@ class PropertyModifierArrayElementByPositionTest extends BaseTestCase
}
/**
* @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*/
public function testGettingFirstFailsForEmptyArray()
{
@ -61,7 +61,7 @@ class PropertyModifierArrayElementByPositionTest extends BaseTestCase
}
/**
* @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*/
public function testGettingLastFailsForEmptyArray()
{
@ -90,7 +90,7 @@ class PropertyModifierArrayElementByPositionTest extends BaseTestCase
}
/**
* @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*/
public function testGettingSpecificFailsForEmptyArray()
{
@ -103,7 +103,7 @@ class PropertyModifierArrayElementByPositionTest extends BaseTestCase
}
/**
* @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*/
public function testGettingSpecificFailsForMissingValue()
{
@ -116,7 +116,7 @@ class PropertyModifierArrayElementByPositionTest extends BaseTestCase
}
/**
* @expectedException InvalidArgumentException
* @expectedException \InvalidArgumentException
*/
public function testFailsForStrings()
{

View File

@ -51,7 +51,7 @@ class PropertyModifierParseURLTest extends BaseTestCase
}
/**
* @expectedException Icinga\Exception\InvalidPropertyException
* @expectedException \Icinga\Exception\InvalidPropertyException
*/
public function testMissingComponentThrowsExceptionOnfailureFail()
{
@ -88,7 +88,7 @@ class PropertyModifierParseURLTest extends BaseTestCase
}
/**
* @expectedException Icinga\Exception\InvalidPropertyException
* @expectedException \Icinga\Exception\InvalidPropertyException
*/
public function testInvalidUrlThrowsExceptionOnfailureFail()
{