ObjectCommand, Exporter: hosts with services

fixes #2565
This commit is contained in:
Thomas Gelf 2022-07-18 11:35:46 +02:00
parent 05d7e137c2
commit c586b2c194
2 changed files with 93 additions and 8 deletions

View File

@ -7,6 +7,7 @@ use Icinga\Exception\MissingParameterException;
use Icinga\Module\Director\Data\Db\DbObject; use Icinga\Module\Director\Data\Db\DbObject;
use Icinga\Module\Director\Data\Exporter; use Icinga\Module\Director\Data\Exporter;
use Icinga\Module\Director\IcingaConfig\IcingaConfig; use Icinga\Module\Director\IcingaConfig\IcingaConfig;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaObject; use Icinga\Module\Director\Objects\IcingaObject;
use InvalidArgumentException; use InvalidArgumentException;
@ -49,17 +50,32 @@ class ObjectCommand extends Command
{ {
$db = $this->db(); $db = $this->db();
$object = $this->getObject(); $object = $this->getObject();
if ($this->params->shift('resolved')) { $exporter = new Exporter($db);
$object = $object::fromPlainObject($object->toPlainObject(true), $db); $resolve = (bool) $this->params->shift('resolved');
$withServices = (bool) $this->params->get('with-services');
if ($withServices) {
if (!$object instanceof IcingaHost) {
$this->fail('--with-services is available for Hosts only');
}
$exporter->enableHostServices();
} }
$exporter->resolveObjects($resolve);
$exporter->showDefaults($this->params->shift('no-defaults', false));
if ($this->params->shift('json')) { if ($this->params->shift('json')) {
$noDefaults = $this->params->shift('no-defaults', false); echo $this->renderJson($exporter->export($object), !$this->params->shift('no-pretty'));
$data = $object->toPlainObject(false, $noDefaults);
echo $this->renderJson($data, !$this->params->shift('no-pretty'));
} else { } else {
$config = new IcingaConfig($db); $config = new IcingaConfig($db);
if ($resolve) {
$object = $object::fromPlainObject($object->toPlainObject(true, false, null, false), $db);
}
$object->renderToConfig($config); $object->renderToConfig($config);
if ($withServices) {
foreach ($exporter->fetchServicesForHost($object) as $service) {
$service->renderToConfig($config);
}
}
foreach ($config->getFiles() as $filename => $content) { foreach ($config->getFiles() as $filename => $content) {
printf("/** %s **/\n\n", $filename); printf("/** %s **/\n\n", $filename);
echo $content; echo $content;

View File

@ -3,6 +3,7 @@
namespace Icinga\Module\Director\Data; namespace Icinga\Module\Director\Data;
use gipfl\ZfDb\Adapter\Adapter; use gipfl\ZfDb\Adapter\Adapter;
use gipfl\ZfDb\Select;
use Icinga\Module\Director\Data\Db\DbObject; use Icinga\Module\Director\Data\Db\DbObject;
use Icinga\Module\Director\Data\Db\DbObjectWithSettings; use Icinga\Module\Director\Data\Db\DbObjectWithSettings;
use Icinga\Module\Director\Db; use Icinga\Module\Director\Db;
@ -11,13 +12,17 @@ use Icinga\Module\Director\Objects\DirectorDatalist;
use Icinga\Module\Director\Objects\DirectorDatalistEntry; use Icinga\Module\Director\Objects\DirectorDatalistEntry;
use Icinga\Module\Director\Objects\DirectorJob; use Icinga\Module\Director\Objects\DirectorJob;
use Icinga\Module\Director\Objects\IcingaCommand; use Icinga\Module\Director\Objects\IcingaCommand;
use Icinga\Module\Director\Objects\IcingaHost;
use Icinga\Module\Director\Objects\IcingaObject; use Icinga\Module\Director\Objects\IcingaObject;
use Icinga\Module\Director\Objects\IcingaService;
use Icinga\Module\Director\Objects\IcingaServiceSet; use Icinga\Module\Director\Objects\IcingaServiceSet;
use Icinga\Module\Director\Objects\IcingaTemplateChoice; use Icinga\Module\Director\Objects\IcingaTemplateChoice;
use Icinga\Module\Director\Objects\ImportRowModifier; use Icinga\Module\Director\Objects\ImportRowModifier;
use Icinga\Module\Director\Objects\ImportSource; use Icinga\Module\Director\Objects\ImportSource;
use Icinga\Module\Director\Objects\InstantiatedViaHook; use Icinga\Module\Director\Objects\InstantiatedViaHook;
use Icinga\Module\Director\Objects\SyncRule; use Icinga\Module\Director\Objects\SyncRule;
use Icinga\Module\Director\Web\Table\ObjectsTableService;
use Ramsey\Uuid\Uuid;
use RuntimeException; use RuntimeException;
class Exporter class Exporter
@ -52,8 +57,21 @@ class Exporter
/** @var FieldReferenceLoader */ /** @var FieldReferenceLoader */
protected $fieldReferenceLoader; protected $fieldReferenceLoader;
/** @var bool */
protected $exportHostServices = false;
protected $showDefaults = false;
protected $resolveObjects = false;
/**
* @var Db
*/
protected $connection;
public function __construct(Db $connection) public function __construct(Db $connection)
{ {
$this->connection = $connection;
$this->db = $connection->getDbAdapter(); $this->db = $connection->getDbAdapter();
$this->fieldReferenceLoader = new FieldReferenceLoader($connection); $this->fieldReferenceLoader = new FieldReferenceLoader($connection);
} }
@ -71,6 +89,24 @@ class Exporter
return (object) $props; return (object) $props;
} }
public function enableHostServices($enable = true)
{
$this->exportHostServices = $enable;
return $this;
}
public function showDefaults($show = true)
{
$this->showDefaults = $show;
return $this;
}
public function resolveObjects($resolve = true)
{
$this->resolveObjects = $resolve;
return $this;
}
protected function appendTypeSpecificRelations(array &$props, DbObject $object) protected function appendTypeSpecificRelations(array &$props, DbObject $object)
{ {
if ($object instanceof DirectorDatalist) { if ($object instanceof DirectorDatalist) {
@ -120,7 +156,34 @@ class Exporter
$props['services'][$serviceObject->getObjectName()] = $this->export($serviceObject); $props['services'][$serviceObject->getObjectName()] = $this->export($serviceObject);
} }
ksort($props['services']); ksort($props['services']);
} elseif ($object instanceof IcingaHost) {
if ($this->exportHostServices) {
$services = [];
foreach ($this->fetchServicesForHost($object) as $service) {
$services[] = $this->export($service);
} }
$props['services'] = $services;
}
}
}
public function fetchServicesForHost(IcingaHost $host)
{
$table = (new ObjectsTableService($this->connection))->setHost($host);
$query = $table->getQuery();
$query->reset(Select::LIMIT_COUNT);
$query->reset(Select::LIMIT_OFFSET);
$services = [];
foreach ($this->db->fetchAll($query) as $row) {
$service = IcingaService::loadWithUniqueId(Uuid::fromBytes($row->uuid), $this->connection);
if ($this->resolveObjects) {
$service = $service::fromPlainObject($service->toPlainObject(true), $this->connection);
}
$services[] = $service;
}
return $services;
} }
protected function loadTemplateName($table, $id) protected function loadTemplateName($table, $id)
@ -158,7 +221,6 @@ class Exporter
unset($props[$key]); unset($props[$key]);
} }
} }
} }
protected function exportRowModifiers(ImportSource $object) protected function exportRowModifiers(ImportSource $object)
@ -172,7 +234,6 @@ class Exporter
return $modifiers; return $modifiers;
} }
public function exportSyncProperties(SyncRule $object) public function exportSyncProperties(SyncRule $object)
{ {
$all = []; $all = [];
@ -208,6 +269,14 @@ class Exporter
$props['settings'] = (object) $object->getSettings(); // Already sorted $props['settings'] = (object) $object->getSettings(); // Already sorted
} }
} }
if (! $this->showDefaults) {
foreach ($props as $key => $value) {
// We assume NULL as a default value for all non-IcingaObject properties
if ($value === null) {
unset($props[$key]);
}
}
}
return $props; return $props;
} }
@ -219,7 +288,7 @@ class Exporter
*/ */
protected function exportIcingaObject(IcingaObject $object) protected function exportIcingaObject(IcingaObject $object)
{ {
$props = (array) $object->toPlainObject(); $props = (array) $object->toPlainObject($this->resolveObjects, !$this->showDefaults);
if ($object->supportsFields()) { if ($object->supportsFields()) {
$props['fields'] = $this->fieldReferenceLoader->loadFor($object); $props['fields'] = $this->fieldReferenceLoader->loadFor($object);
} }