Inspect: completely refactored
* new tree renderer * more tables with details * styling * allow to show status fixes #1003 fixes #1005
This commit is contained in:
parent
f10b85ac9e
commit
e27bb05fb1
|
@ -12,12 +12,6 @@ class EndpointController extends ObjectController
|
||||||
parent::init();
|
parent::init();
|
||||||
if ($this->object && $this->object->hasApiUser()) {
|
if ($this->object && $this->object->hasApiUser()) {
|
||||||
$params['endpoint'] = $this->object->object_name;
|
$params['endpoint'] = $this->object->object_name;
|
||||||
|
|
||||||
$this->getTabs()->add('inspect', array(
|
|
||||||
'url' => 'director/inspect/types',
|
|
||||||
'urlParams' => $params,
|
|
||||||
'label' => $this->translate('Inspect')
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,10 +2,21 @@
|
||||||
|
|
||||||
namespace Icinga\Module\Director\Controllers;
|
namespace Icinga\Module\Director\Controllers;
|
||||||
|
|
||||||
|
use Icinga\Module\Director\Objects\IcingaEndpoint;
|
||||||
|
use Icinga\Module\Director\PlainObjectRenderer;
|
||||||
use Icinga\Module\Director\Web\Controller\ActionController;
|
use Icinga\Module\Director\Web\Controller\ActionController;
|
||||||
|
use Icinga\Module\Director\Web\Table\CoreApiFieldsTable;
|
||||||
|
use Icinga\Module\Director\Web\Table\CoreApiObjectsTable;
|
||||||
|
use Icinga\Module\Director\Web\Table\CoreApiPrototypesTable;
|
||||||
|
use Icinga\Module\Director\Web\Tabs\ObjectTabs;
|
||||||
|
use Icinga\Module\Director\Web\Tree\InspectTreeRenderer;
|
||||||
|
use ipl\Html\Html;
|
||||||
|
use ipl\Html\Link;
|
||||||
|
|
||||||
class InspectController extends ActionController
|
class InspectController extends ActionController
|
||||||
{
|
{
|
||||||
|
private $endpoint;
|
||||||
|
|
||||||
protected function checkDirectorPermissions()
|
protected function checkDirectorPermissions()
|
||||||
{
|
{
|
||||||
$this->assertPermission('director/inspect');
|
$this->assertPermission('director/inspect');
|
||||||
|
@ -13,118 +24,97 @@ class InspectController extends ActionController
|
||||||
|
|
||||||
public function typesAction()
|
public function typesAction()
|
||||||
{
|
{
|
||||||
$api = $this->api();
|
$object = $this->endpoint();
|
||||||
$params = array('name' => $this->view->endpoint);
|
$name = $object->getObjectName();
|
||||||
$this->getTabs()->add('modify', array(
|
$this->tabs(
|
||||||
'url' => 'director/endpoint',
|
new ObjectTabs('endpoint', $this->Auth(), $object)
|
||||||
'urlParams' => $params,
|
)->activate('inspect');
|
||||||
'label' => $this->translate('Endpoint')
|
|
||||||
))->add('render', array(
|
|
||||||
'url' => 'director/endpoint/render',
|
|
||||||
'urlParams' => $params,
|
|
||||||
'label' => $this->translate('Preview'),
|
|
||||||
))->add('history', array(
|
|
||||||
'url' => 'director/endpoint/history',
|
|
||||||
'urlParams' => $params,
|
|
||||||
'label' => $this->translate('History')
|
|
||||||
))->add('inspect', array(
|
|
||||||
'url' => $this->getRequest()->getUrl(),
|
|
||||||
'label' => $this->translate('Inspect')
|
|
||||||
))->activate('inspect');
|
|
||||||
|
|
||||||
$this->view->title = sprintf(
|
$this->addTitle($this->translate('Icinga 2 - Objects: %s'), $name);
|
||||||
$this->translate('Icinga2 Objects: %s'),
|
|
||||||
$this->view->endpoint
|
$this->actions()->add(
|
||||||
|
Link::create(
|
||||||
|
$this->translate('Status'),
|
||||||
|
'director/inspect/status',
|
||||||
|
['endpoint' => $name],
|
||||||
|
[
|
||||||
|
'class' => 'icon-eye',
|
||||||
|
'data-base-target' => '_next'
|
||||||
|
]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
$this->content()->add(
|
||||||
|
new InspectTreeRenderer($object)
|
||||||
);
|
);
|
||||||
$types = $api->getTypes();
|
|
||||||
$rootNodes = array();
|
|
||||||
foreach ($types as $name => $type) {
|
|
||||||
if (property_exists($type, 'base')) {
|
|
||||||
$base = $type->base;
|
|
||||||
if (! property_exists($types[$base], 'children')) {
|
|
||||||
$types[$base]->children = array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$types[$base]->children[$name] = $type;
|
|
||||||
} else {
|
|
||||||
$rootNodes[$name] = $type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
$this->view->types = $rootNodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function typeAction()
|
public function typeAction()
|
||||||
{
|
{
|
||||||
$typeName = $this->params->get('name');
|
$api = $this->endpoint()->api();
|
||||||
$this->singleTab($this->translate('Inspect - object list'));
|
$typeName = $this->params->get('type');
|
||||||
$this->view->title = sprintf(
|
$this->addSingleTab($this->translate('Inspect - object list'));
|
||||||
|
$this->addTitle(
|
||||||
$this->translate('Object type "%s"'),
|
$this->translate('Object type "%s"'),
|
||||||
$typeName
|
$typeName
|
||||||
);
|
);
|
||||||
$this->view->type = $type = $this->api()->getType($typeName);
|
$c = $this->content();
|
||||||
|
$type = $api->getType($typeName);
|
||||||
if ($type->abstract) {
|
if ($type->abstract) {
|
||||||
return;
|
$c->add($this->translate('This is an abstract object type.'));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! empty($type->fields)) {
|
if (! $type->abstract) {
|
||||||
$this->view->objects = $this->api()->listObjects(
|
$objects = $api->listObjects($typeName, $type->plural_name);
|
||||||
$typeName,
|
$c->add(Html::p(sprintf($this->translate('%d objects found'), count($objects))));
|
||||||
$type->plural_name
|
$c->add(new CoreApiObjectsTable($objects, $this->endpoint(), $type));
|
||||||
);
|
}
|
||||||
|
|
||||||
|
if (count((array) $type->fields)) {
|
||||||
|
$c->add([
|
||||||
|
Html::h2($this->translate('Type attributes')),
|
||||||
|
new CoreApiFieldsTable($type->fields, $this->url())
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count($type->prototype_keys)) {
|
||||||
|
$c->add([
|
||||||
|
Html::h2($this->translate('Prototypes (methods)')),
|
||||||
|
new CoreApiPrototypesTable($type->prototype_keys, $type->name)
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public function objectAction()
|
public function objectAction()
|
||||||
{
|
{
|
||||||
$this->singleTab($this->translate('Object Inspection'));
|
$name = $this->params->get('name');
|
||||||
$this->view->object = $this->api()->getObject(
|
$pType = $this->params->get('plural');
|
||||||
$this->params->get('name'),
|
$this->addSingleTab($this->translate('Object Inspection'));
|
||||||
$this->params->get('plural')
|
$object = $this->endpoint()->api()->getObject($name, $pType);
|
||||||
);
|
$this->addTitle('%s "%s"', $pType, $name);
|
||||||
}
|
$this->content()->add(Html::pre(
|
||||||
|
PlainObjectRenderer::render($object)
|
||||||
public function commandsAction()
|
));
|
||||||
{
|
|
||||||
$db = $this->db();
|
|
||||||
echo '<pre>';
|
|
||||||
foreach ($this->api()->setDb($db)->getCheckCommandObjects() as $object) {
|
|
||||||
if (! $object::exists($object->object_name, $db)) {
|
|
||||||
// var_dump($object->store());
|
|
||||||
echo $object;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo '</pre>';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function zonesAction()
|
|
||||||
{
|
|
||||||
$db = $this->db();
|
|
||||||
echo '<pre>';
|
|
||||||
foreach ($this->api()->setDb($db)->getZoneObjects() as $zone) {
|
|
||||||
if (! $zone::exists($zone->object_name, $db)) {
|
|
||||||
// var_dump($zone->store());
|
|
||||||
echo $zone;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
echo '</pre>';
|
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function statusAction()
|
public function statusAction()
|
||||||
{
|
{
|
||||||
$this->view->status = $status = $this->api()->getStatus();
|
$this->addSingleTab($this->translate('Status'));
|
||||||
print_r($status);
|
$this->addTitle($this->translate('Icinga 2 API - Status'));
|
||||||
exit;
|
$this->content()->add(
|
||||||
|
Html::pre(PlainObjectRenderer::render($this->endpoint()->api()->getStatus()))
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function api($endpointName = null)
|
protected function endpoint()
|
||||||
{
|
{
|
||||||
$this->view->endpoint = $this->params->get('endpoint');
|
if ($this->endpoint === null) {
|
||||||
if ($this->view->endpoint === null) {
|
if ($name = $this->params->get('endpoint')) {
|
||||||
$this->view->endpoint = $this->db()->getDeploymentEndpointName();
|
$this->endpoint = IcingaEndpoint::load($name, $this->db());
|
||||||
|
} else {
|
||||||
|
$this->endpoint = $this->db()->getDeploymentEndpointName();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return parent::api($this->view->endpoint);
|
return $this->endpoint;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\Web\Table;
|
||||||
|
|
||||||
|
use ipl\Html\BaseElement;
|
||||||
|
use ipl\Html\Link;
|
||||||
|
use ipl\Html\Table;
|
||||||
|
use ipl\Translation\TranslationHelper;
|
||||||
|
use ipl\Web\Url;
|
||||||
|
|
||||||
|
class CoreApiFieldsTable extends Table
|
||||||
|
{
|
||||||
|
use TranslationHelper;
|
||||||
|
|
||||||
|
protected $defaultAttributes = [
|
||||||
|
'class' => ['common-table'/*, 'table-row-selectable'*/],
|
||||||
|
//'data-base-target' => '_next',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $fields;
|
||||||
|
|
||||||
|
/** @var Url */
|
||||||
|
protected $url;
|
||||||
|
|
||||||
|
public function __construct($fields, Url $url)
|
||||||
|
{
|
||||||
|
$this->url = $url;
|
||||||
|
$this->fields = $fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assemble()
|
||||||
|
{
|
||||||
|
$this->header();
|
||||||
|
$body = $this->body();
|
||||||
|
foreach ($this->fields as $name => $field) {
|
||||||
|
$tr = $this::tr([
|
||||||
|
$this::td($name),
|
||||||
|
$this::td(Link::create(
|
||||||
|
$field->type,
|
||||||
|
$this->url->with('type', $field->type)
|
||||||
|
)),
|
||||||
|
$this::td($field->id)
|
||||||
|
// $this::td($field->array_rank),
|
||||||
|
// $this::td($this->renderKeyValue($field->attributes))
|
||||||
|
]);
|
||||||
|
$this->addAttributeColumns($tr, $field->attributes);
|
||||||
|
$body->add($tr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function addAttributeColumns(BaseElement $tr, $attrs)
|
||||||
|
{
|
||||||
|
$tr->add([
|
||||||
|
$this->makeBooleanColumn($attrs->state),
|
||||||
|
$this->makeBooleanColumn($attrs->config),
|
||||||
|
$this->makeBooleanColumn($attrs->required),
|
||||||
|
$this->makeBooleanColumn($attrs->no_user_modify),
|
||||||
|
$this->makeBooleanColumn($attrs->no_user_view),
|
||||||
|
$this->makeBooleanColumn($attrs->navigation),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function makeBooleanColumn($value)
|
||||||
|
{
|
||||||
|
return $this::td($value ? $this::strong('true') : 'false');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColumnsToBeRendered()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$this->translate('Name'),
|
||||||
|
$this->translate('Type'),
|
||||||
|
$this->translate('Id'),
|
||||||
|
// $this->translate('Array Rank'),
|
||||||
|
// $this->translate('Attributes')
|
||||||
|
$this->translate('State'),
|
||||||
|
$this->translate('Config'),
|
||||||
|
$this->translate('Required'),
|
||||||
|
$this->translate('Protected'),
|
||||||
|
$this->translate('Hidden'),
|
||||||
|
$this->translate('Nav'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderKeyValue($values)
|
||||||
|
{
|
||||||
|
$parts = [];
|
||||||
|
foreach ((array) $values as $key => $value) {
|
||||||
|
if (is_bool($value)) {
|
||||||
|
$value = $value ? 'true' : 'false';
|
||||||
|
}
|
||||||
|
$parts[] = "$key: $value";
|
||||||
|
}
|
||||||
|
|
||||||
|
return implode(', ', $parts);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,57 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\Web\Table;
|
||||||
|
|
||||||
|
use Icinga\Module\Director\Objects\IcingaEndpoint;
|
||||||
|
use ipl\Html\Link;
|
||||||
|
use ipl\Html\Table;
|
||||||
|
use ipl\Translation\TranslationHelper;
|
||||||
|
|
||||||
|
class CoreApiObjectsTable extends Table
|
||||||
|
{
|
||||||
|
use TranslationHelper;
|
||||||
|
|
||||||
|
protected $defaultAttributes = [
|
||||||
|
'class' => ['common-table', 'table-row-selectable'],
|
||||||
|
'data-base-target' => '_next',
|
||||||
|
];
|
||||||
|
|
||||||
|
/** @var IcingaEndpoint */
|
||||||
|
protected $endpoint;
|
||||||
|
|
||||||
|
protected $objects;
|
||||||
|
|
||||||
|
protected $type;
|
||||||
|
|
||||||
|
public function __construct($objects, IcingaEndpoint $endpoint, $type)
|
||||||
|
{
|
||||||
|
$this->objects = $objects;
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
$this->type = $type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assemble()
|
||||||
|
{
|
||||||
|
$this->header();
|
||||||
|
$body = $this->body();
|
||||||
|
foreach ($this->objects as $name) {
|
||||||
|
$body->add($this::tr($this::td(Link::create(
|
||||||
|
str_replace('!', ': ', $name),
|
||||||
|
'director/inspect/object',
|
||||||
|
[
|
||||||
|
'name' => $name,
|
||||||
|
'type' => $this->type->name,
|
||||||
|
'plural' => $this->type->plural_name,
|
||||||
|
'endpoint' => $this->endpoint->getObjectName()
|
||||||
|
]
|
||||||
|
))));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColumnsToBeRendered()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$this->translate('Name'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\Web\Table;
|
||||||
|
|
||||||
|
use ipl\Html\Table;
|
||||||
|
use ipl\Translation\TranslationHelper;
|
||||||
|
|
||||||
|
class CoreApiPrototypesTable extends Table
|
||||||
|
{
|
||||||
|
use TranslationHelper;
|
||||||
|
|
||||||
|
protected $defaultAttributes = ['class' => ['common-table']];
|
||||||
|
|
||||||
|
protected $prototypes;
|
||||||
|
|
||||||
|
protected $typeName;
|
||||||
|
|
||||||
|
public function __construct($prototypes, $typeName)
|
||||||
|
{
|
||||||
|
$this->prototypes = $prototypes;
|
||||||
|
$this->typeName = $typeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assemble()
|
||||||
|
{
|
||||||
|
$this->header();
|
||||||
|
$body = $this->body();
|
||||||
|
$type = $this->typeName;
|
||||||
|
foreach ($this->prototypes as $name) {
|
||||||
|
$body->add($this::tr($this::td("$type.$name()")));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getColumnsToBeRendered()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
$this->translate('Name'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
|
@ -101,6 +101,14 @@ class ObjectTabs extends Tabs
|
||||||
'label' => $this->translate('Members')
|
'label' => $this->translate('Members')
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($object->getShortTableName() === 'endpoint') {
|
||||||
|
$this->add('inspect', [
|
||||||
|
'url' => 'director/inspect/types',
|
||||||
|
'urlParams' => ['endpoint' => $object->getObjectName()],
|
||||||
|
'label' => $this->translate('Inspect')
|
||||||
|
]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function hasFields()
|
protected function hasFields()
|
||||||
|
|
|
@ -0,0 +1,97 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Icinga\Module\Director\Web\Tree;
|
||||||
|
|
||||||
|
use Icinga\Module\Director\Objects\IcingaEndpoint;
|
||||||
|
use ipl\Html\BaseElement;
|
||||||
|
use ipl\Html\Html;
|
||||||
|
use ipl\Html\Link;
|
||||||
|
use ipl\Translation\TranslationHelper;
|
||||||
|
|
||||||
|
class InspectTreeRenderer extends BaseElement
|
||||||
|
{
|
||||||
|
use TranslationHelper;
|
||||||
|
|
||||||
|
protected $tag = 'ul';
|
||||||
|
|
||||||
|
protected $defaultAttributes = [
|
||||||
|
'class' => 'tree',
|
||||||
|
'data-base-target' => '_next',
|
||||||
|
];
|
||||||
|
|
||||||
|
protected $tree;
|
||||||
|
|
||||||
|
/** @var IcingaEndpoint */
|
||||||
|
protected $endpoint;
|
||||||
|
|
||||||
|
public function __construct(IcingaEndpoint $endpoint)
|
||||||
|
{
|
||||||
|
$this->endpoint = $endpoint;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getNodes()
|
||||||
|
{
|
||||||
|
$rootNodes = array();
|
||||||
|
$types = $this->endpoint->api()->getTypes();
|
||||||
|
foreach ($types as $name => $type) {
|
||||||
|
if (property_exists($type, 'base')) {
|
||||||
|
$base = $type->base;
|
||||||
|
if (! property_exists($types[$base], 'children')) {
|
||||||
|
$types[$base]->children = array();
|
||||||
|
}
|
||||||
|
|
||||||
|
$types[$base]->children[$name] = $type;
|
||||||
|
} else {
|
||||||
|
$rootNodes[$name] = $type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $rootNodes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function assemble()
|
||||||
|
{
|
||||||
|
$this->add($this->renderNodes($this->getNodes()));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderNodes($nodes, $showLinks = false, $level = 0)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
foreach ($nodes as $child) {
|
||||||
|
$result[] = $this->renderNode($child, $showLinks, $level + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($level === 0) {
|
||||||
|
return $result;
|
||||||
|
} else {
|
||||||
|
return Html::tag('ul', null, $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function renderNode($node, $forceLinks = false, $level = 0)
|
||||||
|
{
|
||||||
|
$name = $node->name;
|
||||||
|
$showLinks = $forceLinks || $name === 'ConfigObject';
|
||||||
|
$hasChildren = property_exists($node, 'children');
|
||||||
|
$li = Html::tag('li');
|
||||||
|
if (! $hasChildren) {
|
||||||
|
$li->attributes()->add('class', 'collapsed');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($hasChildren) {
|
||||||
|
$li->add(Html::tag('span', ['class' => 'handle']));
|
||||||
|
}
|
||||||
|
|
||||||
|
$class = $node->abstract ? 'icon-sitemap' : 'icon-doc-text';
|
||||||
|
$li->add(Link::create($name, 'director/inspect/type', [
|
||||||
|
'endpoint' => $this->endpoint->getObjectName(),
|
||||||
|
'type' => $name
|
||||||
|
], ['class' => $class]));
|
||||||
|
|
||||||
|
if ($hasChildren) {
|
||||||
|
$li->add($this->renderNodes($node->children, $showLinks, $level + 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
return $li;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue