diff --git a/application/clicommands/TestCommand.php b/application/clicommands/TestCommand.php deleted file mode 100644 index dcb6d170..00000000 --- a/application/clicommands/TestCommand.php +++ /dev/null @@ -1,246 +0,0 @@ -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; - } -} diff --git a/application/controllers/PhperrorController.php b/application/controllers/PhperrorController.php index e091db7a..fbd29d8f 100644 --- a/application/controllers/PhperrorController.php +++ b/application/controllers/PhperrorController.php @@ -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); + } } diff --git a/application/controllers/SyncruleController.php b/application/controllers/SyncruleController.php index 67c62635..eb5467a6 100644 --- a/application/controllers/SyncruleController.php +++ b/application/controllers/SyncruleController.php @@ -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; diff --git a/application/forms/IcingaAddServiceForm.php b/application/forms/IcingaAddServiceForm.php index f39cfb2d..eb49cc2d 100644 --- a/application/forms/IcingaAddServiceForm.php +++ b/application/forms/IcingaAddServiceForm.php @@ -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; diff --git a/application/views/helpers/FormStoredPassword.php b/application/views/helpers/FormStoredPassword.php index 46221c92..be063896 100644 --- a/application/views/helpers/FormStoredPassword.php +++ b/application/views/helpers/FormStoredPassword.php @@ -1,7 +1,7 @@ +
+tabs ?> +

escape($this->title) ?>

+
+ +
+

escape($this->message) ?>

+ + + + + + + + + +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( + '%s (%s)', + $this->escape($module), + $this->escape($module), + $this->translate('more') + ); + } + + \printf( + '', + $link, + $this->escape($required), + $this->escape($installed) + ); +} + +?> + +
translate('Module name') ?>translate('Required') ?>translate('Installed') ?>
%s%s%s
+
diff --git a/doc/02-Installation.md b/doc/02-Installation.md index 306c0f47..09df0016 100644 --- a/doc/02-Installation.md +++ b/doc/02-Installation.md @@ -19,9 +19,9 @@ Requirements * Icinga Web 2 (>= 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 (>= 5.1) or PostgreSQL (>= 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. diff --git a/doc/05-Upgrading.md b/doc/05-Upgrading.md index ebf86c76..57bddfcc 100644 --- a/doc/05-Upgrading.md +++ b/doc/05-Upgrading.md @@ -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. +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. + Upgrading to 1.6.x ------------------------------------------------- diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php index 620a46e0..ded76067 100644 --- a/library/Director/Objects/IcingaObject.php +++ b/library/Director/Objects/IcingaObject.php @@ -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'); } diff --git a/library/Director/Objects/IcingaObjectField.php b/library/Director/Objects/IcingaObjectField.php index 39d8e31b..e18965b7 100644 --- a/library/Director/Objects/IcingaObjectField.php +++ b/library/Director/Objects/IcingaObjectField.php @@ -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) diff --git a/library/Director/Objects/IcingaServiceSetAssignment.php b/library/Director/Objects/IcingaServiceSetAssignment.php index 65fdd2ff..4a6ebbcd 100644 --- a/library/Director/Objects/IcingaServiceSetAssignment.php +++ b/library/Director/Objects/IcingaServiceSetAssignment.php @@ -2,7 +2,7 @@ namespace Icinga\Module\Director\Objects; -class IcingaServiceAssignment extends IcingaObject +class IcingaServiceSetAssignment extends IcingaObject { protected $table = 'icinga_service_set_assignment'; diff --git a/library/Director/Web/Controller/TemplateController.php b/library/Director/Web/Controller/TemplateController.php index 20a77b54..3379f338 100644 --- a/library/Director/Web/Controller/TemplateController.php +++ b/library/Director/Web/Controller/TemplateController.php @@ -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 { diff --git a/library/Director/Web/Table/ObjectsTable.php b/library/Director/Web/Table/ObjectsTable.php index 4d20209e..e62db1e6 100644 --- a/library/Director/Web/Table/ObjectsTable.php +++ b/library/Director/Web/Table/ObjectsTable.php @@ -170,6 +170,11 @@ class ObjectsTable extends ZfQueryBasedTable return $tr; } + protected function getRowClasses($row) + { + return []; + } + protected function applyObjectTypeFilter(ZfSelect $query) { return $query->where( diff --git a/library/Director/Web/Widget/AbstractList.php b/library/Director/Web/Widget/AbstractList.php new file mode 100644 index 00000000..ad1b9e36 --- /dev/null +++ b/library/Director/Web/Widget/AbstractList.php @@ -0,0 +1,40 @@ +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)); + } +} diff --git a/library/Director/Web/Widget/ListItem.php b/library/Director/Web/Widget/ListItem.php new file mode 100644 index 00000000..ec326ccd --- /dev/null +++ b/library/Director/Web/Widget/ListItem.php @@ -0,0 +1,26 @@ +add( + Html::tag('li', $attributes, $content) + ); + } +} diff --git a/library/Director/Web/Widget/OrderedList.php b/library/Director/Web/Widget/OrderedList.php new file mode 100644 index 00000000..8f888de3 --- /dev/null +++ b/library/Director/Web/Widget/OrderedList.php @@ -0,0 +1,8 @@ +=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. diff --git a/run-missingdeps.php b/run-missingdeps.php new file mode 100644 index 00000000..888692de --- /dev/null +++ b/run-missingdeps.php @@ -0,0 +1,23 @@ +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; +} diff --git a/run.php b/run.php index ec074f60..1900a0fa 100644 --- a/run.php +++ b/run.php @@ -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; + } +} diff --git a/test/php/library/Director/PropertyModifier/PropertyModifierArrayElementByPositionTest.php b/test/php/library/Director/PropertyModifier/PropertyModifierArrayElementByPositionTest.php index a915a785..84465f38 100644 --- a/test/php/library/Director/PropertyModifier/PropertyModifierArrayElementByPositionTest.php +++ b/test/php/library/Director/PropertyModifier/PropertyModifierArrayElementByPositionTest.php @@ -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() { diff --git a/test/php/library/Director/PropertyModifier/PropertyModifierParseURLTest.php b/test/php/library/Director/PropertyModifier/PropertyModifierParseURLTest.php index 53c303fe..a5ccb796 100644 --- a/test/php/library/Director/PropertyModifier/PropertyModifierParseURLTest.php +++ b/test/php/library/Director/PropertyModifier/PropertyModifierParseURLTest.php @@ -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() {