Deployment: add Info class, refactor LogRenderer

No more view script, based on ipl
This commit is contained in:
Thomas Gelf 2017-07-20 11:06:20 +02:00
parent 406bc8bd72
commit 31d65fadc2
4 changed files with 187 additions and 121 deletions

View File

@ -4,8 +4,7 @@ namespace Icinga\Module\Director\Controllers;
use Icinga\Module\Director\Web\Controller\ActionController;
use Icinga\Module\Director\Objects\DirectorDeploymentLog;
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
use Icinga\Module\Director\Util;
use Icinga\Module\Director\Web\Widget\DeploymentInfo;
class DeploymentController extends ActionController
{
@ -16,30 +15,14 @@ class DeploymentController extends ActionController
public function indexAction()
{
$this->view->title = $this->translate('Deployment details');
$deploymentId = $this->params->get('id');
$this->view->deployment = $deployment = DirectorDeploymentLog::load(
$deploymentId,
$info = new DeploymentInfo(DirectorDeploymentLog::load(
$this->params->get('id'),
$this->db()
);
$this->view->config_checksum = Util::binary2hex($deployment->config_checksum);
$this->view->config = IcingaConfig::load($deployment->config_checksum, $this->db());
$tabs = $this->getTabs()->add('deployment', array(
'label' => $this->translate('Deployment'),
'url' => $this->getRequest()->getUrl()
))->activate('deployment');
if ($deployment->config_checksum !== null && $this->hasPermission('director/showconfig')) {
$tabs->add('config', array(
'label' => $this->translate('Config'),
'url' => 'director/config/files',
'urlParams' => array(
'checksum' => $this->view->config_checksum,
'deployment_id' => $deploymentId
)
));
}
));
$this->addTitle($this->translate('Deployment details'));
$this->tabs(
$info->getTabs($this->getAuth(), $this->getRequest())
)->activate('deployment');
$this->content()->add($info);
}
}

View File

@ -1,81 +0,0 @@
<?php
use Icinga\Util\Format;
use Icinga\Module\Director\StartupLogRenderer;
?><div class="controls">
<?= $this->tabs ?>
<h1><?= $this->escape($this->title) ?></h1>
</div>
<div class="content">
<table class="name-value-table">
<tr>
<th><?= $this->translate('Deployment time') ?></th>
<td><?= $deployment->start_time ?></td>
</tr>
<tr>
<th><?= $this->translate('Sent to') ?></th>
<td><?= $deployment->peer_identity ?></td>
</tr>
<tr>
<th><?= $this->translate('Configuration') ?></th>
<td><?= $this->qlink(
sprintf(
$this->translate('%d files'),
$this->config->getFileCount()
),
'director/config/files',
array(
'checksum' => $config_checksum,
'deployment_id' => $deployment->id
)
) ?>, <?= sprintf(
$this->translate('%d objects, %d templates, %d apply rules'),
$config->getObjectCount(),
$config->getTemplateCount(),
$config->getApplyCount()
)?>, <?= Format::bytes($config->getSize()) ?></td>
</tr>
<tr>
<th><?= $this->translate('Duration') ?></th>
<td><?= sprintf(
$this->translate('Rendered in %0.2fs, deployed in %0.2fs'),
$config->getDuration() / 1000,
$deployment->duration_dump / 1000
) ?></td>
</tr>
<tr>
<th><?= $this->translate('Stage name') ?></th>
<td><?= $deployment->stage_name ?></td>
</tr>
<tr>
<th><?= $this->translate('Startup') ?></th>
<td><?php
if ($deployment->startup_succeeded === null) {
if ($deployment->stage_collected === null) {
echo $this->translate('Unknown, still waiting for config check outcome') . ' ' . $this->icon('spinner');
} else {
echo $this->translate('Unknown, failed to collect related information') . ' ' . $this->icon('help');
}
} elseif ($deployment->startup_succeeded === 'y') {
echo '<div style="color: green">';
echo $this->translate('Succeeded') . ' ' . $this->icon('ok');
echo '</div>';
} else {
echo '<div style="color: red">';
echo $this->translate('Failed') . ' ' . $this->icon('cancel');
echo '</div>';
}
?></td>
</tr>
</table>
<?php if ($deployment->startup_succeeded !== null): ?>
<h2>Startup log</h2>
<pre class="logfile">
<?= StartupLogRenderer::beautify($deployment, $this) ?>
</pre>
<?php endif ?>
</div>

View File

@ -3,13 +3,24 @@
namespace Icinga\Module\Director;
use Icinga\Module\Director\Objects\DirectorDeploymentLog;
use Icinga\Web\View;
use ipl\Html\Link;
use ipl\Html\Util;
use ipl\Html\ValidHtml;
class StartupLogRenderer
class StartupLogRenderer implements ValidHtml
{
public static function beautify(DirectorDeploymentLog $deploymentLog, View $view)
/** @var DirectorDeploymentLog */
protected $deployment;
public function __construct(DirectorDeploymentLog $deployment)
{
$log = $view->escape($deploymentLog->get('startup_log'));
$this->deployment = $deployment;
}
public function render()
{
$deployment = $this->deployment;
$log = Util::escapeForHtml($deployment->get('startup_log'));
$lines = array();
$severity = 'information';
$sevPattern = '/^(debug|notice|information|warning|critical)\/(\w+)/';
@ -35,11 +46,12 @@ class StartupLogRenderer
$line = preg_replace('/([\^]{2,})/', '<span class="error-hint">\1</span>', $line);
$markPattern = null;
$self = $this;
if (preg_match($filePatternHint, $line, $m)) {
$line = preg_replace_callback(
$filePatternHint,
function ($matches) use ($severity, $view, $deploymentLog) {
return StartupLogRenderer::logLink($matches, $severity, $deploymentLog, $view);
function ($matches) use ($severity, $self) {
return $self->logLink($matches, $severity);
},
$line
);
@ -51,8 +63,8 @@ class StartupLogRenderer
$line = preg_replace_callback(
$filePatternDetail,
function ($matches) use ($severity, $view, $deploymentLog) {
return StartupLogRenderer::logLink($matches, $severity, $deploymentLog, $view);
function ($matches) use ($severity, $self) {
return $self->logLink($matches, $severity);
},
$line
);
@ -63,7 +75,7 @@ class StartupLogRenderer
return implode("\n", $lines);
}
public static function logLink($match, $severity, DirectorDeploymentLog $deploymentLog, View $view)
protected function logLink($match, $severity)
{
$stageDir = $match[1];
$filename = $match[2];
@ -74,9 +86,10 @@ class StartupLogRenderer
$lineNumber = null;
}
$deployment = $this->deployment;
$params = array(
'config_checksum' => $deploymentLog->getConfigHexChecksum(),
'deployment_id' => $deploymentLog->get('id'),
'config_checksum' => $deployment->getConfigHexChecksum(),
'deployment_id' => $deployment->get('id'),
'file_path' => $filename,
'backTo' => 'deployment'
);
@ -85,13 +98,13 @@ class StartupLogRenderer
$params['highlightSeverity'] = $severity;
}
return $view->qlink(
return Link::create(
'[stage]/' . $filename,
'director/config/file',
$params,
array(
[
'title' => $stageDir . $filename
)
]
) . $suffix;
}
}

View File

@ -0,0 +1,151 @@
<?php
namespace Icinga\Module\Director\Web\Widget;
use Icinga\Authentication\Auth;
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
use Icinga\Module\Director\Objects\DirectorDeploymentLog;
use Icinga\Module\Director\StartupLogRenderer;
use Icinga\Util\Format;
use Icinga\Web\Request;
use ipl\Html\Html;
use ipl\Html\Icon;
use ipl\Html\Link;
use ipl\Translation\TranslationHelper;
use ipl\Web\Widget\NameValueTable;
use ipl\Web\Widget\Tabs;
class DeploymentInfo extends Html
{
use TranslationHelper;
/** @var DirectorDeploymentLog */
protected $deployment;
/** @var IcingaConfig */
protected $config;
public function __construct(DirectorDeploymentLog $deployment)
{
$this->deployment = $deployment;
$this->config = IcingaConfig::load(
$deployment->config_checksum,
$deployment->getConnection()
);
}
public function getTabs(Auth $auth, Request $request)
{
$dep = $this->deployment;
$tabs = new Tabs();
$tabs->add('deployment', array(
'label' => $this->translate('Deployment'),
'url' => $request->getUrl()
))->activate('deployment');
if ($dep->config_checksum !== null && $auth->hasPermission('director/showconfig')) {
$tabs->add('config', array(
'label' => $this->translate('Config'),
'url' => 'director/config/files',
'urlParams' => array(
'checksum' => $this->config->getHexChecksum(),
'deployment_id' => $dep->id
)
));
}
return $tabs;
}
protected function createInfoTable()
{
$dep = $this->deployment;
$table = new NameValueTable();
$table->addNameValuePairs([
$this->translate('Deployment time') => $dep->start_time,
$this->translate('Sent to') => $dep->peer_identity,
$this->translate('Configuration') => $this->getConfigDetails(),
$this->translate('Duration') => $this->getDurationInfo(),
$this->translate('Stage name') => $dep->stage_name,
$this->translate('Startup') => $this->getStartupInfo()
]);
return $table;
}
protected function getDurationInfo()
{
return sprintf(
$this->translate('Rendered in %0.2fs, deployed in %0.2fs'),
$this->config->getDuration() / 1000,
$this->deployment->duration_dump / 1000
);
}
protected function getConfigDetails()
{
$cfg = $this->config;
$dep = $this->deployment;
return [
Link::create(
sprintf($this->translate('%d files'), $cfg->getFileCount()),
'director/config/files',
[
'checksum' => $cfg->getHexChecksum(),
'deployment_id' => $dep->id
]
),
', ',
sprintf(
$this->translate('%d objects, %d templates, %d apply rules'),
$cfg->getObjectCount(),
$cfg->getTemplateCount(),
$cfg->getApplyCount()
),
', ',
Format::bytes($cfg->getSize())
];
}
protected function getStartupInfo()
{
$dep = $this->deployment;
if ($dep->startup_succeeded === null) {
if ($dep->stage_collected === null) {
return [$this->translate('Unknown, still waiting for config check outcome'), new Icon('spinner')];
} else {
return [$this->translate('Unknown, failed to collect related information'), new Icon('help')];
}
} elseif ($dep->startup_succeeded === 'y') {
return $this->colored('green', [$this->translate('Succeeded'), new Icon('ok')]);
} else {
return $this->colored('red', [$this->translate('Failed'), new Icon('cancel')]);
}
}
protected function colored($color, array $content)
{
return Html::tag('div', ['style' => "color: $color;"], $content)->setSeparator(' ');
}
public function render()
{
$this->add($this->createInfoTable());
if ($this->deployment->get('startup_succeeded') !== null) {
$this->addStartupLog();
}
return parent::render();
}
protected function addStartupLog()
{
$this->add(Html::h2($this->translate('Startup Log')));
$this->add(
Html::tag('pre', [
'class' => 'logfile'
], new StartupLogRenderer($this->deployment))
);
}
}