summaryrefslogtreecommitdiffstats
path: root/library/Director/Objects
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:17:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-14 13:17:48 +0000
commite6d4dfc040bbe3cb80a2ce65b82493b557f751fc (patch)
tree40bd6366b01b06f4d96fc8638f23a772263cb5e9 /library/Director/Objects
parentReleasing progress-linux version 1.10.2-2~progress7.99u1. (diff)
downloadicingaweb2-module-director-e6d4dfc040bbe3cb80a2ce65b82493b557f751fc.tar.xz
icingaweb2-module-director-e6d4dfc040bbe3cb80a2ce65b82493b557f751fc.zip
Merging upstream version 1.11.1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'library/Director/Objects')
-rw-r--r--library/Director/Objects/DirectorActivityLog.php15
-rw-r--r--library/Director/Objects/DirectorDatafield.php101
-rw-r--r--library/Director/Objects/DirectorDatalist.php118
-rw-r--r--library/Director/Objects/DirectorDatalistEntry.php2
-rw-r--r--library/Director/Objects/DirectorDeploymentLog.php6
-rw-r--r--library/Director/Objects/DirectorJob.php87
-rw-r--r--library/Director/Objects/GroupMembershipResolver.php32
-rw-r--r--library/Director/Objects/IcingaArguments.php8
-rw-r--r--library/Director/Objects/IcingaCommand.php91
-rw-r--r--library/Director/Objects/IcingaDependency.php90
-rw-r--r--library/Director/Objects/IcingaHost.php85
-rw-r--r--library/Director/Objects/IcingaHostGroup.php8
-rw-r--r--library/Director/Objects/IcingaNotification.php125
-rw-r--r--library/Director/Objects/IcingaObject.php94
-rw-r--r--library/Director/Objects/IcingaObjectGroup.php64
-rw-r--r--library/Director/Objects/IcingaObjectGroups.php6
-rw-r--r--library/Director/Objects/IcingaObjectLegacyAssignments.php2
-rw-r--r--library/Director/Objects/IcingaObjectMultiRelations.php2
-rw-r--r--library/Director/Objects/IcingaRelatedObject.php2
-rw-r--r--library/Director/Objects/IcingaService.php107
-rw-r--r--library/Director/Objects/IcingaServiceGroup.php8
-rw-r--r--library/Director/Objects/IcingaServiceSet.php280
-rw-r--r--library/Director/Objects/IcingaTemplateChoice.php63
-rw-r--r--library/Director/Objects/IcingaTemplateResolver.php1
-rw-r--r--library/Director/Objects/IcingaTimePeriod.php44
-rw-r--r--library/Director/Objects/IcingaUser.php37
-rw-r--r--library/Director/Objects/ImportExportHelper.php68
-rw-r--r--library/Director/Objects/ImportRowModifier.php15
-rw-r--r--library/Director/Objects/ImportSource.php79
-rw-r--r--library/Director/Objects/ObjectApplyMatches.php2
-rw-r--r--library/Director/Objects/SyncRule.php70
31 files changed, 506 insertions, 1206 deletions
diff --git a/library/Director/Objects/DirectorActivityLog.php b/library/Director/Objects/DirectorActivityLog.php
index cb041b6..2cecc2e 100644
--- a/library/Director/Objects/DirectorActivityLog.php
+++ b/library/Director/Objects/DirectorActivityLog.php
@@ -7,6 +7,7 @@ use Icinga\Module\Director\Db;
use Icinga\Authentication\Auth;
use Icinga\Application\Icinga;
use Icinga\Application\Logger;
+use stdClass;
class DirectorActivityLog extends DbObject
{
@@ -176,7 +177,19 @@ class DirectorActivityLog extends DbObject
{
$name = $object->getObjectName();
$type = $object->getTableName();
- $oldProps = json_encode($object->getPlainUnmodifiedObject());
+ /** @var stdClass $plainUnmodifiedObject */
+ $plainUnmodifiedObject = $object->getPlainUnmodifiedObject();
+
+ if ($object instanceof IcingaServiceSet) {
+ $services = [];
+ foreach ($object->getCachedServices() as $service) {
+ $services[$service->getObjectName()] = $service->toPlainObject();
+ }
+
+ $plainUnmodifiedObject->services = $services;
+ }
+
+ $oldProps = json_encode($plainUnmodifiedObject);
$data = [
'object_name' => $name,
diff --git a/library/Director/Objects/DirectorDatafield.php b/library/Director/Objects/DirectorDatafield.php
index 84db068..ced6218 100644
--- a/library/Director/Objects/DirectorDatafield.php
+++ b/library/Director/Objects/DirectorDatafield.php
@@ -2,28 +2,30 @@
namespace Icinga\Module\Director\Objects;
-use Icinga\Module\Director\Core\Json;
use Icinga\Module\Director\Data\Db\DbObjectWithSettings;
use Icinga\Module\Director\Db;
+use Icinga\Module\Director\DirectorObject\Automation\BasketSnapshotFieldResolver;
use Icinga\Module\Director\DirectorObject\Automation\CompareBasketObject;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\Forms\IcingaServiceForm;
use Icinga\Module\Director\Hook\DataTypeHook;
use Icinga\Module\Director\Resolver\OverriddenVarsResolver;
use Icinga\Module\Director\Web\Form\DirectorObjectForm;
-use InvalidArgumentException;
+use Ramsey\Uuid\Uuid;
+use stdClass;
use Zend_Form_Element as ZfElement;
class DirectorDatafield extends DbObjectWithSettings
{
protected $table = 'director_datafield';
-
protected $keyName = 'id';
-
protected $autoincKeyName = 'id';
+ protected $uuidColumn = 'uuid';
+ protected $settingsTable = 'director_datafield_setting';
+ protected $settingsRemoteId = 'datafield_id';
protected $defaultProperties = [
'id' => null,
+ 'uuid' => null,
'category_id' => null,
'varname' => null,
'caption' => null,
@@ -33,16 +35,11 @@ class DirectorDatafield extends DbObjectWithSettings
];
protected $relations = [
- 'category' => 'DirectorDatafieldCategory'
+ 'category' => 'DirectorDatafieldCategory'
];
- protected $settingsTable = 'director_datafield_setting';
-
- protected $settingsRemoteId = 'datafield_id';
-
- /** @var DirectorDatafieldCategory|null */
+ /** @var ?DirectorDatafieldCategory */
private $category;
-
private $object;
public static function fromDbRow($row, Db $connection)
@@ -70,10 +67,9 @@ class DirectorDatafield extends DbObjectWithSettings
}
/**
- * @return DirectorDatafieldCategory|null
* @throws \Icinga\Exception\NotFoundError
*/
- public function getCategory()
+ public function getCategory(): ?DirectorDatafieldCategory
{
if ($this->category) {
return $this->category;
@@ -84,7 +80,7 @@ class DirectorDatafield extends DbObjectWithSettings
}
}
- public function getCategoryName()
+ public function getCategoryName(): ?string
{
$category = $this->getCategory();
if ($category === null) {
@@ -105,27 +101,26 @@ class DirectorDatafield extends DbObjectWithSettings
}
$this->category = $category;
} else {
- if (DirectorDatafieldCategory::exists($category, $this->getConnection())) {
- $this->setCategory(DirectorDatafieldCategory::load($category, $this->getConnection()));
+ if ($category = DirectorDatafieldCategory::loadOptional($category, $this->getConnection())) {
+ $this->setCategory($category);
} else {
$this->setCategory(DirectorDatafieldCategory::create([
'category_name' => $category
], $this->getConnection()));
}
}
-
- return $this;
}
/**
- * @return object
* @throws \Icinga\Exception\NotFoundError
*/
- public function export()
+ public function export(): stdClass
{
$plain = (object) $this->getProperties();
- $plain->originalId = $plain->id;
unset($plain->id);
+ if ($uuid = $this->get('uuid')) {
+ $plain->uuid = Uuid::fromBytes($uuid)->toString();
+ }
$plain->settings = (object) $this->getSettings();
if (property_exists($plain->settings, 'datalist_id')) {
@@ -144,63 +139,35 @@ class DirectorDatafield extends DbObjectWithSettings
}
/**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return DirectorDatafield
* @throws \Icinga\Exception\NotFoundError
*/
- public static function import($plain, Db $db, $replace = false)
+ public static function import(stdClass $plain, Db $db): DirectorDatafield
{
- $properties = (array) $plain;
- if (isset($properties['originalId'])) {
- $id = $properties['originalId'];
- unset($properties['originalId']);
- } else {
- $id = null;
- }
-
- if (isset($properties['settings']->datalist)) {
- // Just try to load the list, import should fail if missing
- $list = DirectorDatalist::load(
- $properties['settings']->datalist,
- $db
- );
- } else {
- $list = null;
- }
-
- $compare = Json::decode(Json::encode($properties));
- if ($id && static::exists($id, $db)) {
- $existing = static::loadWithAutoIncId($id, $db);
- $existingProperties = (array) $existing->export();
- unset($existingProperties['originalId']);
- if (CompareBasketObject::equals((object) $compare, (object) $existingProperties)) {
- return $existing;
+ $dba = $db->getDbAdapter();
+ if ($uuid = $plain->uuid ?? null) {
+ $uuid = Uuid::fromString($uuid);
+ if ($candidate = DirectorDatafield::loadWithUniqueId($uuid, $db)) {
+ BasketSnapshotFieldResolver::fixOptionalDatalistReference($plain, $db);
+ assert($candidate instanceof DirectorDatafield);
+ $candidate->setProperties((array) $plain);
+ return $candidate;
}
}
-
- if ($list) {
- unset($properties['settings']->datalist);
- $properties['settings']->datalist_id = $list->get('id');
- }
-
- $dba = $db->getDbAdapter();
- $query = $dba->select()
- ->from('director_datafield')
- ->where('varname = ?', $plain->varname);
+ $query = $dba->select()->from('director_datafield')->where('varname = ?', $plain->varname);
$candidates = DirectorDatafield::loadAll($db, $query);
foreach ($candidates as $candidate) {
$export = $candidate->export();
- unset($export->originalId);
CompareBasketObject::normalize($export);
- if (CompareBasketObject::equals($export, $compare)) {
+ unset($export->uuid);
+ unset($plain->originalId);
+ if (CompareBasketObject::equals($export, $plain)) {
return $candidate;
}
}
+ BasketSnapshotFieldResolver::fixOptionalDatalistReference($plain, $db);
- return static::create($properties, $db);
+ return static::create((array) $plain, $db);
}
protected function beforeStore()
@@ -223,7 +190,7 @@ class DirectorDatafield extends DbObjectWithSettings
return $this->object;
}
- public function getFormElement(DirectorObjectForm $form, $name = null)
+ public function getFormElement(DirectorObjectForm $form, $name = null): ?ZfElement
{
$className = $this->get('datatype');
@@ -305,7 +272,7 @@ class DirectorDatafield extends DbObjectWithSettings
}
}
- protected function eventuallyGetResolvedCommandVar(IcingaObject $object, $varName)
+ protected function eventuallyGetResolvedCommandVar(IcingaObject $object, $varName): ?array
{
if (! $object->hasRelation('check_command')) {
return null;
diff --git a/library/Director/Objects/DirectorDatalist.php b/library/Director/Objects/DirectorDatalist.php
index ae5c983..1bb821b 100644
--- a/library/Director/Objects/DirectorDatalist.php
+++ b/library/Director/Objects/DirectorDatalist.php
@@ -4,68 +4,35 @@ namespace Icinga\Module\Director\Objects;
use Exception;
use Icinga\Module\Director\Data\Db\DbObject;
-use Icinga\Module\Director\Db;
+use Icinga\Module\Director\DataType\DataTypeDatalist;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
use Icinga\Module\Director\Exception\DuplicateKeyException;
class DirectorDatalist extends DbObject implements ExportInterface
{
protected $table = 'director_datalist';
-
protected $keyName = 'list_name';
-
protected $autoincKeyName = 'id';
+ protected $uuidColumn = 'uuid';
- protected $defaultProperties = array(
+ protected $defaultProperties = [
'id' => null,
+ 'uuid' => null,
'list_name' => null,
'owner' => null
- );
+ ];
/** @var DirectorDatalistEntry[] */
- protected $storedEntries;
+ protected $entries;
public function getUniqueIdentifier()
{
return $this->get('list_name');
}
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return static
- * @throws \Icinga\Exception\NotFoundError
- * @throws DuplicateKeyException
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- if (isset($properties['originalId'])) {
- unset($properties['originalId']);
- } else {
- $id = null;
- }
- $name = $properties['list_name'];
-
- if ($replace && static::exists($name, $db)) {
- $object = static::load($name, $db);
- } elseif (static::exists($name, $db)) {
- throw new DuplicateKeyException(
- 'Data List %s already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
- $object->setProperties($properties);
-
- return $object;
- }
-
- public function setEntries($entries)
+ public function setEntries($entries): void
{
- $existing = $this->getStoredEntries();
+ $existing = $this->getEntries();
$new = [];
$seen = [];
@@ -101,15 +68,13 @@ class DirectorDatalist extends DbObject implements ExportInterface
$this->hasBeenModified = true;
}
- $this->storedEntries = $existing;
- ksort($this->storedEntries);
-
- return $this;
+ $this->entries = $existing;
+ ksort($this->entries);
}
protected function beforeDelete()
{
- if ($this->hasBeenUsed()) {
+ if ($this->isInUse()) {
throw new Exception(
sprintf(
"Cannot delete '%s', as the datalist '%s' is currently being used.",
@@ -120,9 +85,13 @@ class DirectorDatalist extends DbObject implements ExportInterface
}
}
- protected function hasBeenUsed()
+ protected function isInUse(): bool
{
- $datalistType = 'Icinga\\Module\\Director\\DataType\\DataTypeDatalist';
+ $id = $this->get('id');
+ if ($id === null) {
+ return false;
+ }
+
$db = $this->getDb();
$dataFieldsCheck = $db->select()
@@ -137,8 +106,8 @@ class DirectorDatalist extends DbObject implements ExportInterface
'l.id = dfs.setting_value',
[]
)
- ->where('datatype = ?', $datalistType)
- ->where('setting_value = ?', $this->get('id'));
+ ->where('datatype = ?', DataTypeDatalist::class)
+ ->where('setting_value = ?', $id);
if ($db->fetchOne($dataFieldsCheck)) {
return true;
@@ -147,7 +116,7 @@ class DirectorDatalist extends DbObject implements ExportInterface
$syncCheck = $db->select()
->from(['sp' =>'sync_property'], ['source_expression'])
->where('sp.destination_field = ?', 'list_id')
- ->where('sp.source_expression = ?', $this->get('id'));
+ ->where('sp.source_expression = ?', $id);
if ($db->fetchOne($syncCheck)) {
return true;
@@ -161,65 +130,38 @@ class DirectorDatalist extends DbObject implements ExportInterface
*/
public function onStore()
{
- if ($this->storedEntries) {
+ if ($this->entries) {
$db = $this->getConnection();
$removedKeys = [];
$myId = $this->get('id');
- foreach ($this->storedEntries as $key => $entry) {
+ foreach ($this->entries as $key => $entry) {
if ($entry->shouldBeRemoved()) {
$entry->delete();
$removedKeys[] = $key;
} else {
- if (! $entry->hasBeenLoadedFromDb()) {
- $entry->set('list_id', $myId);
- }
$entry->set('list_id', $myId);
$entry->store($db);
}
}
foreach ($removedKeys as $key) {
- unset($this->storedEntries[$key]);
- }
- }
- }
-
- /**
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @return object
- */
- public function export()
- {
- $plain = (object) $this->getProperties();
- $plain->originalId = $plain->id;
- unset($plain->id);
-
- $plain->entries = [];
- foreach ($this->getStoredEntries() as $key => $entry) {
- if ($entry->shouldBeRemoved()) {
- continue;
+ unset($this->entries[$key]);
}
- $plainEntry = (object) $entry->getProperties();
- unset($plainEntry->list_id);
-
- $plain->entries[] = $plainEntry;
}
-
- return $plain;
}
- protected function getStoredEntries()
+ public function getEntries(): array
{
- if ($this->storedEntries === null) {
- if ($id = $this->get('id')) {
- $this->storedEntries = DirectorDatalistEntry::loadAllForList($this);
- ksort($this->storedEntries);
+ if ($this->entries === null) {
+ if ($this->get('id')) {
+ $this->entries = DirectorDatalistEntry::loadAllForList($this);
+ ksort($this->entries);
} else {
- $this->storedEntries = [];
+ $this->entries = [];
}
}
- return $this->storedEntries;
+ return $this->entries;
}
}
diff --git a/library/Director/Objects/DirectorDatalistEntry.php b/library/Director/Objects/DirectorDatalistEntry.php
index 086686a..278de97 100644
--- a/library/Director/Objects/DirectorDatalistEntry.php
+++ b/library/Director/Objects/DirectorDatalistEntry.php
@@ -51,7 +51,7 @@ class DirectorDatalistEntry extends DbObject
} else {
throw new RuntimeException(
'Expected array or null for allowed_roles, got %s',
- var_export($roles, 1)
+ var_export($roles, true)
);
}
}
diff --git a/library/Director/Objects/DirectorDeploymentLog.php b/library/Director/Objects/DirectorDeploymentLog.php
index 0794a3c..e9b07ce 100644
--- a/library/Director/Objects/DirectorDeploymentLog.php
+++ b/library/Director/Objects/DirectorDeploymentLog.php
@@ -46,7 +46,11 @@ class DirectorDeploymentLog extends DbObject
public function getConfigHexChecksum()
{
- return bin2hex($this->config_checksum);
+ $checksum = $this->get('config_checksum');
+ if ($checksum === null) {
+ return null;
+ }
+ return bin2hex($checksum);
}
public function getConfig()
diff --git a/library/Director/Objects/DirectorJob.php b/library/Director/Objects/DirectorJob.php
index 361f764..2a18d52 100644
--- a/library/Director/Objects/DirectorJob.php
+++ b/library/Director/Objects/DirectorJob.php
@@ -122,8 +122,12 @@ class DirectorJob extends DbObjectWithSettings implements ExportInterface, Insta
return false;
}
+ if ($this->get('ts_last_attempt') === null) {
+ return true;
+ }
+
return (
- strtotime((int) $this->get('ts_last_attempt')) + $this->get('run_interval') * 2
+ strtotime($this->get('ts_last_attempt')) + $this->get('run_interval') * 2
) < time();
}
@@ -194,87 +198,6 @@ class DirectorJob extends DbObjectWithSettings implements ExportInterface, Insta
}
/**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
- {
- $plain = (object) $this->getProperties();
- $plain->originalId = $plain->id;
- unset($plain->id);
- unset($plain->timeperiod_id);
- if ($this->hasTimeperiod()) {
- $plain->timeperiod = $this->timeperiod()->getObjectName();
- }
-
- foreach ($this->stateProperties as $key) {
- unset($plain->$key);
- }
- $plain->settings = $this->getInstance()->exportSettings();
-
- return $plain;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return DirectorJob
- * @throws DuplicateKeyException
- * @throws NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $dummy = new static;
- $idCol = $dummy->autoincKeyName;
- $keyCol = $dummy->keyName;
- $properties = (array) $plain;
- if (isset($properties['originalId'])) {
- $id = $properties['originalId'];
- unset($properties['originalId']);
- } else {
- $id = null;
- }
- $name = $properties[$keyCol];
-
- if ($replace && $id && static::existsWithNameAndId($name, $id, $db)) {
- $object = static::loadWithAutoIncId($id, $db);
- } elseif ($replace && static::exists($name, $db)) {
- $object = static::load($name, $db);
- } elseif (static::exists($name, $db)) {
- throw new DuplicateKeyException(
- 'Director Job "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- $settings = (array) $properties['settings'];
-
- if (array_key_exists('source', $settings) && ! (array_key_exists('source_id', $settings))) {
- $val = ImportSource::load($settings['source'], $db)->get('id');
- $settings['source_id'] = $val;
- unset($settings['source']);
- }
-
- if (array_key_exists('rule', $settings) && ! (array_key_exists('rule_id', $settings))) {
- $val = SyncRule::load($settings['rule'], $db)->get('id');
- $settings['rule_id'] = $val;
- unset($settings['rule']);
- }
-
- $properties['settings'] = (object) $settings;
- $object->setProperties($properties);
- if ($id !== null) {
- $object->reallySet($idCol, $id);
- }
-
- return $object;
- }
-
- /**
* @param string $name
* @param int $id
* @param Db $connection
diff --git a/library/Director/Objects/GroupMembershipResolver.php b/library/Director/Objects/GroupMembershipResolver.php
index f5ef418..7266de9 100644
--- a/library/Director/Objects/GroupMembershipResolver.php
+++ b/library/Director/Objects/GroupMembershipResolver.php
@@ -211,7 +211,7 @@ abstract class GroupMembershipResolver
$query,
$object,
'o',
- Db\IcingaObjectFilterHelper::INHERIT_DIRECT_OR_INDIRECT
+ IcingaObjectFilterHelper::INHERIT_DIRECT_OR_INDIRECT
);
foreach ($object::loadAll($this->connection, $query) as $child) {
@@ -352,7 +352,7 @@ abstract class GroupMembershipResolver
$type = $this->type;
if ($this->groupMap === null) {
$this->groupMap = $this->db->fetchPairs(
- $this->db->select()->from("icinga_${type}group", ['object_name', 'id'])
+ $this->db->select()->from("icinga_{$type}group", ['object_name', 'id'])
);
}
@@ -390,9 +390,9 @@ abstract class GroupMembershipResolver
$db->delete(
$this->getResolvedTableName(),
sprintf(
- "(${type}group_id = %d AND ${type}_id = %d)",
- $row["${type}group_id"],
- $row["${type}_id"]
+ "({$type}group_id = %d AND {$type}_id = %d)",
+ $row["{$type}group_id"],
+ $row["{$type}_id"]
)
);
}
@@ -416,16 +416,16 @@ abstract class GroupMembershipResolver
foreach ($objectIds as $objectId) {
if (! array_key_exists($objectId, $right[$groupId])) {
$diff[] = array(
- "${type}group_id" => $groupId,
- "${type}_id" => $objectId,
+ "{$type}group_id" => $groupId,
+ "{$type}_id" => $objectId,
);
}
}
} else {
foreach ($objectIds as $objectId) {
$diff[] = array(
- "${type}group_id" => $groupId,
- "${type}_id" => $objectId,
+ "{$type}group_id" => $groupId,
+ "{$type}_id" => $objectId,
);
}
}
@@ -445,16 +445,16 @@ abstract class GroupMembershipResolver
$query = $this->db->select()->from(
array('hgh' => $this->getResolvedTableName()),
array(
- 'group_id' => "${type}group_id",
- 'object_id' => "${type}_id",
+ 'group_id' => "{$type}group_id",
+ 'object_id' => "{$type}_id",
)
);
- $this->addMembershipWhere($query, "${type}_id", $this->objects);
- $this->addMembershipWhere($query, "${type}group_id", $this->groups);
+ $this->addMembershipWhere($query, "{$type}_id", $this->objects);
+ $this->addMembershipWhere($query, "{$type}group_id", $this->groups);
if (! empty($this->groups)) {
// load staticGroups (we touched here) additionally, so we can compare changes
- $this->addMembershipWhere($query, "${type}group_id", $this->staticGroups);
+ $this->addMembershipWhere($query, "{$type}group_id", $this->staticGroups);
}
foreach ($this->db->fetchAll($query) as $row) {
@@ -602,7 +602,7 @@ abstract class GroupMembershipResolver
{
$type = $this->getType();
$query = $this->db->select()->from(
- array('hg' => "icinga_${type}group"),
+ array('hg' => "icinga_{$type}group"),
array(
'id',
'assign_filter',
@@ -629,7 +629,7 @@ abstract class GroupMembershipResolver
protected function getTableName()
{
$type = $this->getType();
- return "icinga_${type}group_${type}";
+ return "icinga_{$type}group_{$type}";
}
protected function getResolvedTableName()
diff --git a/library/Director/Objects/IcingaArguments.php b/library/Director/Objects/IcingaArguments.php
index e788da8..22bf914 100644
--- a/library/Director/Objects/IcingaArguments.php
+++ b/library/Director/Objects/IcingaArguments.php
@@ -155,7 +155,9 @@ class IcingaArguments implements Iterator, Countable, IcingaConfigRenderer
if (property_exists($value, 'type')) {
// argument is directly set as function, no further properties
if ($value->type === 'Function') {
- $attrs['argument_value'] = self::COMMENT_DSL_UNSUPPORTED;
+ $attrs['argument_value'] = property_exists($value, 'body')
+ ? $value->body
+ : self::COMMENT_DSL_UNSUPPORTED;
$attrs['argument_format'] = 'expression';
}
} elseif (property_exists($value, 'value')) {
@@ -296,6 +298,7 @@ class IcingaArguments implements Iterator, Countable, IcingaConfigRenderer
$this->arguments = IcingaCommandArgument::loadAll($connection, $query, 'argument_name');
$this->cloneStored();
$this->refreshIndex();
+ $this->modified = false;
return $this;
}
@@ -360,6 +363,7 @@ class IcingaArguments implements Iterator, Countable, IcingaConfigRenderer
}
$this->refreshIndex();
$this->cloneStored();
+ $this->modified = false;
}
/**
@@ -393,7 +397,9 @@ class IcingaArguments implements Iterator, Countable, IcingaConfigRenderer
unset($this->arguments[$key]);
}
+ $this->refreshIndex();
$this->cloneStored();
+ $this->modified = false;
return $this;
}
diff --git a/library/Director/Objects/IcingaCommand.php b/library/Director/Objects/IcingaCommand.php
index 35f38a4..8c5aed0 100644
--- a/library/Director/Objects/IcingaCommand.php
+++ b/library/Director/Objects/IcingaCommand.php
@@ -2,9 +2,7 @@
namespace Icinga\Module\Director\Objects;
-use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1;
use Icinga\Module\Director\Objects\Extension\Arguments;
@@ -129,10 +127,8 @@ class IcingaCommand extends IcingaObject implements ObjectWithArguments, ExportI
// return $value;
}
- if (self::$pluginDir !== null) {
- if (($pos = strpos($value, self::$pluginDir)) === 0) {
- $value = substr($value, strlen(self::$pluginDir) + 1);
- }
+ if (isset($value, self::$pluginDir) && strpos($value, self::$pluginDir) === 0) {
+ $value = substr($value, strlen(self::$pluginDir) + 1);
}
return $value;
@@ -212,89 +208,6 @@ class IcingaCommand extends IcingaObject implements ObjectWithArguments, ExportI
return $this->getObjectName();
}
- /**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
- {
- $props = (array) $this->toPlainObject();
- if (isset($props['arguments'])) {
- foreach ($props['arguments'] as $key => $argument) {
- if (property_exists($argument, 'command_id')) {
- unset($props['arguments'][$key]->command_id);
- }
- }
- }
- $props['fields'] = $this->loadFieldReferences();
- ksort($props);
-
- return (object) $props;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaCommand
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- $name = $properties['object_name'];
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Command "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- unset($properties['fields']);
- $object->setProperties($properties);
-
- return $object;
- }
-
- /**
- * @deprecated please use \Icinga\Module\Director\Data\FieldReferenceLoader
- * @return array
- */
- protected function loadFieldReferences()
- {
- $db = $this->getDb();
-
- $res = $db->fetchAll(
- $db->select()->from([
- 'cf' => 'icinga_command_field'
- ], [
- 'cf.datafield_id',
- 'cf.is_required',
- 'cf.var_filter',
- ])->join(['df' => 'director_datafield'], 'df.id = cf.datafield_id', [])
- ->where('command_id = ?', $this->get('id'))
- ->order('varname ASC')
- );
-
- if (empty($res)) {
- return [];
- } else {
- foreach ($res as $field) {
- $field->datafield_id = (int) $field->datafield_id;
- }
-
- return $res;
- }
- }
-
protected function renderCommand()
{
$command = $this->get('command');
diff --git a/library/Director/Objects/IcingaDependency.php b/library/Director/Objects/IcingaDependency.php
index c9d9b89..abd92e6 100644
--- a/library/Director/Objects/IcingaDependency.php
+++ b/library/Director/Objects/IcingaDependency.php
@@ -3,9 +3,7 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Exception\ConfigurationError;
-use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
use Icinga\Exception\NotFoundError;
use Icinga\Data\Filter\Filter;
@@ -80,52 +78,21 @@ class IcingaDependency extends IcingaObject implements ExportInterface
return $this->getObjectName();
}
- /**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
+ public function parentHostIsVar()
{
- $props = (array) $this->toPlainObject();
- ksort($props);
-
- return (object) $props;
+ return $this->get('parent_host_var') !== null;
}
/**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return static
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
+ * Check if the given string is a custom variable
+ *
+ * @param $string string
+ *
+ * @return false|int
*/
- public static function import($plain, Db $db, $replace = false)
+ protected function isCustomVar(string $string)
{
- $properties = (array) $plain;
- $name = $properties['object_name'];
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Dependency "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- $object->setProperties($properties);
-
- return $object;
- }
-
- public function parentHostIsVar()
- {
- return $this->get('parent_host_var') !== null;
+ return preg_match('/^(?:host|service)\.vars\..+$/', $string);
}
/**
@@ -485,9 +452,16 @@ class IcingaDependency extends IcingaObject implements ExportInterface
public function renderParent_service_by_name()
{
// @codingStandardsIgnoreEnd
+ $var = $this->get('parent_service_by_name');
+ if ($this->isCustomVar($var)) {
+ return c::renderKeyValue(
+ 'parent_service_name',
+ $var
+ );
+ }
return c::renderKeyValue(
'parent_service_name',
- c::renderString($this->get('parent_service_by_name'))
+ c::renderString($var)
);
}
@@ -506,7 +480,7 @@ class IcingaDependency extends IcingaObject implements ExportInterface
protected function resolveUnresolvedRelatedProperty($name)
{
$short = substr($name, 0, -3);
- /** @var IcingaObject $class */
+ /** @var IcingaObject|string $class */
$class = $this->getRelationClass($short);
$objKey = $this->unresolvedRelatedProperties[$name];
@@ -589,7 +563,25 @@ class IcingaDependency extends IcingaObject implements ExportInterface
$this->reallySet($name, $object->get('id'));
unset($this->unresolvedRelatedProperties[$name]);
} else {
- throw new NotFoundError('Unable to resolve related property: "%s"', $name);
+ // Depend on a single service on a single host. Rare case, as usually you want to
+ // depend on a service on the very same host - and leave the Host field empty. The
+ // latter is already being handled above. This duplicates some code, but I'll leave
+ // it this way for now. There might have been a reason for the parent_host_id = null
+ // check in that code.
+ if ($name === 'parent_service_id' && $this->get('object_type') === 'apply') {
+ $this->reallySet(
+ 'parent_service_by_name',
+ $this->unresolvedRelatedProperties[$name]
+ );
+ $this->reallySet('parent_service_id', null);
+ unset($this->unresolvedRelatedProperties[$name]);
+ return;
+ }
+ throw new NotFoundError(sprintf(
+ 'Unable to resolve related property: %s "%s"',
+ $name,
+ $this->unresolvedRelatedProperties[$name]
+ ));
}
}
@@ -620,8 +612,12 @@ class IcingaDependency extends IcingaObject implements ExportInterface
$related = parent::getRelatedProperty($key);
// handle special case for plain string parent service on Dependency
// Apply rules
- if ($related === null && $key === 'parent_service'
- && null !== $this->get('parent_service_by_name')
+ if ($related === null
+ && $key === 'parent_service'
+ && (
+ $this->get('parent_service_by_name')
+ && ! $this->isCustomVar($this->get('parent_service_by_name'))
+ )
) {
return $this->get('parent_service_by_name');
}
diff --git a/library/Director/Objects/IcingaHost.php b/library/Director/Objects/IcingaHost.php
index 2731f4a..7859324 100644
--- a/library/Director/Objects/IcingaHost.php
+++ b/library/Director/Objects/IcingaHost.php
@@ -7,7 +7,6 @@ use Icinga\Exception\NotFoundError;
use Icinga\Module\Director\Data\PropertiesFilter;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1;
@@ -310,88 +309,18 @@ class IcingaHost extends IcingaObject implements ExportInterface
}
}
- /**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
+ protected function rendersConditionalTemplate(): bool
{
- // TODO: ksort in toPlainObject?
- $props = (array) $this->toPlainObject();
- $props['fields'] = $this->loadFieldReferences();
- ksort($props);
-
- return (object) $props;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaHost
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- $name = $properties['object_name'];
- if ($properties['object_type'] !== 'template') {
- throw new InvalidArgumentException(sprintf(
- 'Can import only Templates, got "%s" for "%s"',
- $properties['object_type'],
- $name
- ));
- }
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Service Template "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- // $object->newFields = $properties['fields'];
- unset($properties['fields']);
- $object->setProperties($properties);
-
- return $object;
+ return $this->getRenderingZone() === self::ALL_NON_GLOBAL_ZONES;
}
- /**
- * @deprecated please use \Icinga\Module\Director\Data\FieldReferenceLoader
- * @return array
- */
- protected function loadFieldReferences()
+ protected function getDefaultZone(IcingaConfig $config = null)
{
- $db = $this->getDb();
-
- $res = $db->fetchAll(
- $db->select()->from([
- 'hf' => 'icinga_host_field'
- ], [
- 'hf.datafield_id',
- 'hf.is_required',
- 'hf.var_filter',
- ])->join(['df' => 'director_datafield'], 'df.id = hf.datafield_id', [])
- ->where('host_id = ?', $this->get('id'))
- ->order('varname ASC')
- );
-
- if (empty($res)) {
- return [];
- } else {
- foreach ($res as $field) {
- $field->datafield_id = (int) $field->datafield_id;
- }
- return $res;
+ if ($this->isTemplate()) {
+ return self::ALL_NON_GLOBAL_ZONES;
}
+
+ return parent::getDefaultZone();
}
public function beforeDelete()
diff --git a/library/Director/Objects/IcingaHostGroup.php b/library/Director/Objects/IcingaHostGroup.php
index e11f672..e78e931 100644
--- a/library/Director/Objects/IcingaHostGroup.php
+++ b/library/Director/Objects/IcingaHostGroup.php
@@ -31,12 +31,8 @@ class IcingaHostGroup extends IcingaObjectGroup
return $this;
}
- protected function notifyResolvers()
+ protected function getMemberShipResolver()
{
- $resolver = $this->getHostGroupMembershipResolver();
- $resolver->addGroup($this);
- $resolver->refreshDb();
-
- return $this;
+ return $this->getHostGroupMembershipResolver();
}
}
diff --git a/library/Director/Objects/IcingaNotification.php b/library/Director/Objects/IcingaNotification.php
index 9c5d08d..4768704 100644
--- a/library/Director/Objects/IcingaNotification.php
+++ b/library/Director/Objects/IcingaNotification.php
@@ -2,9 +2,8 @@
namespace Icinga\Module\Director\Objects;
-use Icinga\Module\Director\Db;
+use Icinga\Module\Director\CustomVariable\CustomVariables;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
use RuntimeException;
@@ -29,6 +28,8 @@ class IcingaNotification extends IcingaObject implements ExportInterface
'notification_interval' => null,
'period_id' => null,
'zone_id' => null,
+ 'users_var' => null,
+ 'user_groups_var' => null,
'assign_filter' => null,
];
@@ -85,92 +86,76 @@ class IcingaNotification extends IcingaObject implements ExportInterface
* @codingStandardsIgnoreStart
* @return string
*/
- protected function renderTimes_end()
+ protected function renderUsers_var()
{
// @codingStandardsIgnoreEnd
- return c::renderKeyValue('times.end', c::renderInterval($this->get('times_end')));
- }
-
- public function getUniqueIdentifier()
- {
- return $this->getObjectName();
+ return '';
}
/**
- * @return \stdClass
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
+ * @codingStandardsIgnoreStart
+ * @return string
*/
- public function export()
+ protected function renderUser_groups_var()
{
- // TODO: ksort in toPlainObject?
- $props = (array) $this->toPlainObject();
- $props['fields'] = $this->loadFieldReferences();
- ksort($props);
-
- return (object) $props;
+ // @codingStandardsIgnoreEnd
+ return '';
}
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return static
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
+ protected function renderUserVarsSuffixFor($property)
{
- $properties = (array) $plain;
- $name = $properties['object_name'];
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Notification "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
+ $varName = $this->getResolvedProperty("{$property}_var");
+ if ($varName === null) {
+ return '';
+ }
+
+ $varSuffix = CustomVariables::renderKeySuffix($varName);
+ $indent = ' ';
+ $objectType = $this->get('apply_to');
+ if ($objectType === 'service') {
+ return "{$indent}if (service.vars$varSuffix) {\n"
+ . c::renderKeyOperatorValue($property, '+=', "service.vars$varSuffix", $indent . ' ')
+ . "$indent} else {\n"
+ . $this->getHostSnippet($indent . ' ')
+ . "$indent if (host.vars$varSuffix) { "
+ . c::renderKeyOperatorValue($property, '+=', "host.vars$varSuffix }", '')
+ . "$indent}\n";
+ } elseif ($objectType === 'host') {
+ return $this->getHostSnippet()
+ . "{$indent}if (host.vars$varSuffix) { "
+ . c::renderKeyOperatorValue($property, '+=', "host.vars$varSuffix }");
}
- // $object->newFields = $properties['fields'];
- unset($properties['fields']);
- $object->setProperties($properties);
+ return '';
+ }
+
+ protected function getHostSnippet($indent = ' ')
+ {
+ return "{$indent}if (! host) {\n"
+ . "$indent var host = get_host(host_name)\n"
+ . "$indent}\n";
+ }
- return $object;
+ protected function renderSuffix()
+ {
+ return $this->renderUserVarsSuffixFor('users')
+ . $this->renderUserVarsSuffixFor('user_groups')
+ . parent::renderSuffix();
}
/**
- * @deprecated please use \Icinga\Module\Director\Data\FieldReferenceLoader
- * @return array
+ * @codingStandardsIgnoreStart
+ * @return string
*/
- protected function loadFieldReferences()
+ protected function renderTimes_end()
{
- $db = $this->getDb();
-
- $res = $db->fetchAll(
- $db->select()->from([
- 'nf' => 'icinga_notification_field'
- ], [
- 'nf.datafield_id',
- 'nf.is_required',
- 'nf.var_filter',
- ])->join(['df' => 'director_datafield'], 'df.id = nf.datafield_id', [])
- ->where('notification_id = ?', $this->get('id'))
- ->order('varname ASC')
- );
-
- if (empty($res)) {
- return [];
- } else {
- foreach ($res as $field) {
- $field->datafield_id = (int) $field->datafield_id;
- }
- return $res;
- }
+ // @codingStandardsIgnoreEnd
+ return c::renderKeyValue('times.end', c::renderInterval($this->get('times_end')));
+ }
+
+ public function getUniqueIdentifier()
+ {
+ return $this->getObjectName();
}
/**
diff --git a/library/Director/Objects/IcingaObject.php b/library/Director/Objects/IcingaObject.php
index 04ae32b..3b6236d 100644
--- a/library/Director/Objects/IcingaObject.php
+++ b/library/Director/Objects/IcingaObject.php
@@ -27,6 +27,7 @@ use RuntimeException;
abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
{
const RESOLVE_ERROR = '(unable to resolve)';
+ const ALL_NON_GLOBAL_ZONES = '(all non-global zones)';
protected $keyName = 'object_name';
@@ -63,9 +64,6 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
protected $type;
- /* key/value!! */
- protected $booleans = [];
-
// Property suffixed with _id must exist
protected $relations = [
// property => PropertyClass
@@ -142,11 +140,6 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
return $this->connection;
}
- public function propertyIsBoolean($property)
- {
- return array_key_exists($property, $this->booleans);
- }
-
public function propertyIsInterval($property)
{
return array_key_exists($property, $this->intervalProperties);
@@ -771,10 +764,6 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
return $this;
}
- if ($this->propertyIsBoolean($key)) {
- return parent::set($key, DbDataFormatter::normalizeBoolean($value));
- }
-
// e.g. zone_id
if ($this->propertyIsRelation($key)) {
return $this->setRelation($key, $value);
@@ -906,20 +895,20 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
$type = strtolower($this->getType());
$query = $this->db->select()->from(
- ['gr' => "icinga_${type}group_${type}_resolved"],
+ ['gr' => "icinga_{$type}group_{$type}_resolved"],
['g.object_name']
)->join(
- ['g' => "icinga_${type}group"],
- "g.id = gr.${type}group_id",
+ ['g' => "icinga_{$type}group"],
+ "g.id = gr.{$type}group_id",
[]
)->joinLeft(
- ['go' => "icinga_${type}group_${type}"],
- "go.${type}group_id = gr.${type}group_id AND go.${type}_id = " . (int) $id,
+ ['go' => "icinga_{$type}group_{$type}"],
+ "go.{$type}group_id = gr.{$type}group_id AND go.{$type}_id = " . (int) $id,
[]
)->where(
- "gr.${type}_id = ?",
+ "gr.{$type}_id = ?",
(int) $id
- )->where("go.${type}_id IS NULL")->order('g.object_name');
+ )->where("go.{$type}_id IS NULL")->order('g.object_name');
return $this->db->fetchCol($query);
}
@@ -1812,9 +1801,21 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
return;
}
- $config->configFile(
- 'zones.d/' . $this->getRenderingZone($config) . '/' . $this->getRenderingFilename()
- )->addObject($this);
+ foreach ($this->getRenderingZones($config) as $zone) {
+ $config->configFile(
+ 'zones.d/' . $zone . '/' . $this->getRenderingFilename()
+ )->addObject($this);
+ }
+ }
+
+ protected function getRenderingZones(IcingaConfig $config): array
+ {
+ $zone = $this->getRenderingZone($config);
+ if ($zone === self::ALL_NON_GLOBAL_ZONES) {
+ return $config->listNonGlobalZones();
+ }
+
+ return [$zone];
}
public function getRenderingFilename()
@@ -2193,7 +2194,12 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
protected function renderSuffix()
{
- return "}\n\n";
+ $prefix = '';
+ if ($this->rendersConditionalTemplate()) {
+ $prefix = '} ';
+ }
+
+ return "$prefix}\n\n";
}
protected function renderLegacySuffix()
@@ -2418,14 +2424,25 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
protected function renderObjectHeader()
{
+ $prefix = '';
+ $renderedName = c::renderString($this->getObjectName());
+ if ($this->rendersConditionalTemplate()) {
+ $prefix = sprintf('if (! get_template(%s, %s)) { ', $this->getType(), $renderedName);
+ }
return sprintf(
- "%s %s %s {\n",
+ "%s%s %s %s {\n",
+ $prefix,
$this->getObjectTypeName(),
$this->getType(),
- c::renderString($this->getObjectName())
+ $renderedName
);
}
+ protected function rendersConditionalTemplate(): bool
+ {
+ return false;
+ }
+
public function getLegacyObjectType()
{
return strtolower($this->getType());
@@ -2674,16 +2691,16 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
/** @var DbObject $class */
$class = DbObjectTypeRegistry::classByType($type);
+ if ($keyColumn === null && is_array($class::create()->getKeyName())) {
+ return $class::loadAll($db, $query);
+ }
+
if ($keyColumn === null) {
if (method_exists($class, 'getKeyColumnName')) {
$keyColumn = $class::getKeyColumnName();
}
}
- if (is_array($class::create()->getKeyName())) {
- return $class::loadAll($db, $query);
- }
-
if (PrefetchCache::shouldBeUsed()
&& $query === null
&& $keyColumn === static::getKeyColumnName()
@@ -2890,11 +2907,14 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
}
}
}
+ if ($this->propertyIsInterval($k) && is_string($v) && ctype_digit($v)) {
+ $v = (int) $v;
+ }
// TODO: Do not ship null properties based on flag?
if (!$skipDefaults || $this->differsFromDefaultValue($k, $v)) {
if ($k === 'disabled' || $this->propertyIsBoolean($k)) {
- $props[$k] = $this->booleanForDbValue($v);
+ $props[$k] = DbDataFormatter::booleanForDbValue($v);
} else {
$props[$k] = $v;
}
@@ -3005,18 +3025,6 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
return (object) $props;
}
- protected function booleanForDbValue($value)
- {
- if ($value === 'y') {
- return true;
- }
- if ($value === 'n') {
- return false;
- }
-
- return $value; // let this fail elsewhere, if not null
- }
-
public function listImportNames()
{
if ($this->gotImports()) {
@@ -3161,7 +3169,7 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
if ($this->differsFromDefaultValue($k, $v)) {
if ($k === 'disabled' || $this->propertyIsBoolean($k)) {
- $props[$k] = $this->booleanForDbValue($v);
+ $props[$k] = DbDataFormatter::booleanForDbValue($v);
} else {
$props[$k] = $v;
}
diff --git a/library/Director/Objects/IcingaObjectGroup.php b/library/Director/Objects/IcingaObjectGroup.php
index c0bec54..c076f52 100644
--- a/library/Director/Objects/IcingaObjectGroup.php
+++ b/library/Director/Objects/IcingaObjectGroup.php
@@ -2,9 +2,7 @@
namespace Icinga\Module\Director\Objects;
-use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
abstract class IcingaObjectGroup extends IcingaObject implements ExportInterface
{
@@ -24,53 +22,51 @@ abstract class IcingaObjectGroup extends IcingaObject implements ExportInterface
'assign_filter' => null,
];
+ protected $memberShipShouldBeRefreshed = false;
+
public function getUniqueIdentifier()
{
return $this->getObjectName();
}
- /**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
+ protected function prefersGlobalZone()
{
- return $this->toPlainObject();
+ return true;
}
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaObjectGroup
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
+ protected function beforeStore()
{
- $properties = (array) $plain;
- $name = $properties['object_name'];
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Group "%s" already exists',
- $name
- );
+ parent::beforeStore();
+ if ($this->hasBeenLoadedFromDb()) {
+ if (!array_key_exists('assign_filter', $this->getModifiedProperties())) {
+ $this->memberShipShouldBeRefreshed = false;
+ return;
+ }
} else {
- $object = static::create([], $db);
+ if ($this->hasProperty('assign_filter') && $this->get('assign_filter') === null) {
+ $this->memberShipShouldBeRefreshed = false;
+ return;
+ }
}
- $object->setProperties($properties);
+ if ($this->hasProperty('assign_filter')) {
+ $this->memberShipShouldBeRefreshed = true;
+ }
+ }
- return $object;
+ protected function notifyResolvers()
+ {
+ if ($this->memberShipShouldBeRefreshed) {
+ $resolver = $this->getMemberShipResolver();
+ $resolver->addGroup($this);
+ $resolver->refreshDb();
+ }
+
+ return $this;
}
- protected function prefersGlobalZone()
+ protected function getMemberShipResolver()
{
- return true;
+ return null;
}
}
diff --git a/library/Director/Objects/IcingaObjectGroups.php b/library/Director/Objects/IcingaObjectGroups.php
index 8bef1b1..8683c77 100644
--- a/library/Director/Objects/IcingaObjectGroups.php
+++ b/library/Director/Objects/IcingaObjectGroups.php
@@ -183,6 +183,10 @@ class IcingaObjectGroups implements Iterator, Countable, IcingaConfigRenderer
return $this;
}
+ if (is_int($group)) {
+ $group = (string) $group;
+ }
+
/** @var IcingaObjectGroup $class */
$class = $this->getGroupClass();
@@ -224,7 +228,7 @@ class IcingaObjectGroups implements Iterator, Countable, IcingaConfigRenderer
} else {
throw new RuntimeException(
'Invalid group object: %s',
- var_export($group, 1)
+ var_export($group, true)
);
}
diff --git a/library/Director/Objects/IcingaObjectLegacyAssignments.php b/library/Director/Objects/IcingaObjectLegacyAssignments.php
index 6ab75c8..2db29b4 100644
--- a/library/Director/Objects/IcingaObjectLegacyAssignments.php
+++ b/library/Director/Objects/IcingaObjectLegacyAssignments.php
@@ -36,7 +36,7 @@ class IcingaObjectLegacyAssignments
$assigns = array();
$ignores = array();
foreach ($values as $type => $value) {
- if (strpos($value, '|') !== false || strpos($value, '&' !== false)) {
+ if (strpos($value, '|') !== false || strpos($value, '&') !== false) {
$value = '(' . $value . ')';
}
diff --git a/library/Director/Objects/IcingaObjectMultiRelations.php b/library/Director/Objects/IcingaObjectMultiRelations.php
index a1ec9a2..5931595 100644
--- a/library/Director/Objects/IcingaObjectMultiRelations.php
+++ b/library/Director/Objects/IcingaObjectMultiRelations.php
@@ -239,7 +239,7 @@ class IcingaObjectMultiRelations implements Iterator, Countable, IcingaConfigRen
} else {
throw new ProgrammingError(
'Invalid related object: %s',
- var_export($relation, 1)
+ var_export($relation, true)
);
}
diff --git a/library/Director/Objects/IcingaRelatedObject.php b/library/Director/Objects/IcingaRelatedObject.php
index d35bcb0..ca33688 100644
--- a/library/Director/Objects/IcingaRelatedObject.php
+++ b/library/Director/Objects/IcingaRelatedObject.php
@@ -180,7 +180,7 @@ class IcingaRelatedObject
} else {
throw new ProgrammingError(
'Related object can be name or object, got: %s',
- var_export($related, 1)
+ var_export($related, true)
);
}
diff --git a/library/Director/Objects/IcingaService.php b/library/Director/Objects/IcingaService.php
index 9479ef7..cbf9ca5 100644
--- a/library/Director/Objects/IcingaService.php
+++ b/library/Director/Objects/IcingaService.php
@@ -8,7 +8,6 @@ use Icinga\Module\Director\Data\PropertiesFilter;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\Cache\PrefetchCache;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
use Icinga\Module\Director\IcingaConfig\IcingaLegacyConfigHelper as c1;
@@ -170,94 +169,6 @@ class IcingaService extends IcingaObject implements ExportInterface
}
/**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
- {
- // TODO: ksort in toPlainObject?
- $props = (array) $this->toPlainObject();
- $props['fields'] = $this->loadFieldReferences();
- ksort($props);
-
- return (object) $props;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaService
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- $name = $properties['object_name'];
- if ($properties['object_type'] !== 'template') {
- throw new InvalidArgumentException(sprintf(
- 'Can import only Templates, got "%s" for "%s"',
- $properties['object_type'],
- $name
- ));
- }
- $key = [
- 'object_type' => 'template',
- 'object_name' => $name
- ];
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Service Template "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- // $object->newFields = $properties['fields'];
- unset($properties['fields']);
- $object->setProperties($properties);
-
- return $object;
- }
-
- /**
- * @deprecated please use \Icinga\Module\Director\Data\FieldReferenceLoader
- * @return array
- */
- protected function loadFieldReferences()
- {
- $db = $this->getDb();
-
- $res = $db->fetchAll(
- $db->select()->from([
- 'sf' => 'icinga_service_field'
- ], [
- 'sf.datafield_id',
- 'sf.is_required',
- 'sf.var_filter',
- ])->join(['df' => 'director_datafield'], 'df.id = sf.datafield_id', [])
- ->where('service_id = ?', $this->get('id'))
- ->order('varname ASC')
- );
-
- if (empty($res)) {
- return [];
- } else {
- foreach ($res as $field) {
- $field->datafield_id = (int) $field->datafield_id;
- }
-
- return $res;
- }
- }
-
- /**
* @param string $key
* @return $this
*/
@@ -473,6 +384,11 @@ class IcingaService extends IcingaObject implements ExportInterface
}
}
+ protected function rendersConditionalTemplate(): bool
+ {
+ return $this->getRenderingZone() === self::ALL_NON_GLOBAL_ZONES;
+ }
+
/**
* @return bool
*/
@@ -667,11 +583,22 @@ class IcingaService extends IcingaObject implements ExportInterface
protected function getDefaultZone(IcingaConfig $config = null)
{
+ // Hint: this isn't possible yet, as we're unable to render dependent apply rules to multiple zones as well
+ // if ($this->isTemplate()) {
+ // return self::ALL_NON_GLOBAL_ZONES;
+ // }
if ($this->get('host_id') === null) {
return parent::getDefaultZone();
} else {
- return $this->getRelatedObject('host', $this->get('host_id'))
+ $zone = $this->getRelatedObject('host', $this->get('host_id'))
->getRenderingZone($config);
+
+ // Hint: this avoids problems with host templates rendered to all non-global zones
+ if ($zone === self::ALL_NON_GLOBAL_ZONES) {
+ $zone = $this->connection->getDefaultGlobalZoneName();
+ }
+
+ return $zone;
}
}
diff --git a/library/Director/Objects/IcingaServiceGroup.php b/library/Director/Objects/IcingaServiceGroup.php
index ae43ff3..92fb1cb 100644
--- a/library/Director/Objects/IcingaServiceGroup.php
+++ b/library/Director/Objects/IcingaServiceGroup.php
@@ -31,12 +31,8 @@ class IcingaServiceGroup extends IcingaObjectGroup
return $this;
}
- protected function notifyResolvers()
+ protected function getMemberShipResolver()
{
- $resolver = $this->getServiceGroupMembershipResolver();
- $resolver->addGroup($this);
- $resolver->refreshDb();
-
- return $this;
+ return $this->getServiceGroupMembershipResolver();
}
}
diff --git a/library/Director/Objects/IcingaServiceSet.php b/library/Director/Objects/IcingaServiceSet.php
index 8217a59..252c52a 100644
--- a/library/Director/Objects/IcingaServiceSet.php
+++ b/library/Director/Objects/IcingaServiceSet.php
@@ -5,16 +5,14 @@ namespace Icinga\Module\Director\Objects;
use Exception;
use Icinga\Data\Filter\Filter;
use Icinga\Module\Director\Data\Db\ServiceSetQueryBuilder;
-use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\Cache\PrefetchCache;
-use Icinga\Module\Director\Db\DbUtil;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\IcingaConfig\IcingaConfig;
use Icinga\Module\Director\Resolver\HostServiceBlacklist;
use InvalidArgumentException;
use Ramsey\Uuid\Uuid;
-use RuntimeException;
+use stdClass;
class IcingaServiceSet extends IcingaObject implements ExportInterface
{
@@ -46,6 +44,33 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
'host' => 'IcingaHost',
);
+ /** @var IcingaService[] Cached services */
+ protected $cachedServices = [];
+
+ /** @var IcingaService[]|null */
+ private $services;
+
+ /**
+ * Set the services to be cached
+ *
+ * @param $services IcingaService[]
+ * @return void
+ */
+ public function setCachedServices($services)
+ {
+ $this->cachedServices = $services;
+ }
+
+ /**
+ * Get the cached services
+ *
+ * @return IcingaService[]
+ */
+ public function getCachedServices()
+ {
+ return $this->cachedServices;
+ }
+
public function isDisabled()
{
return false;
@@ -79,6 +104,61 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
}
/**
+ * @param stdClass[] $services
+ * @return void
+ */
+ public function setServices(array $services)
+ {
+ $existing = $this->getServices();
+ $uuidMap = [];
+ foreach ($existing as $service) {
+ $uuidMap[$service->getUniqueId()->getBytes()] = $service;
+ }
+ $this->services = [];
+ foreach ($services as $service) {
+ if (isset($service->uuid)) {
+ $uuid = Uuid::fromString($service->uuid)->getBytes();
+ $current = $uuidMap[$uuid] ?? IcingaService::create([], $this->connection);
+ } else {
+ if (! is_object($service)) {
+ var_dump($service);
+ exit;
+ }
+ $current = $existing[$service->object_name] ?? IcingaService::create([], $this->connection);
+ }
+ $current->setProperties((array) $service);
+ $this->services[] = $current;
+ }
+ }
+
+ protected function storeRelatedServices()
+ {
+ if ($this->services === null) {
+ $cachedServices = $this->getCachedServices();
+ if ($cachedServices) {
+ $this->services = $cachedServices;
+ } else {
+ return;
+ }
+ }
+
+ $seen = [];
+ /** @var IcingaService $service */
+ foreach ($this->services as $service) {
+ $seen[$service->getUniqueId()->getBytes()] = true;
+ $service->set('service_set_id', $this->get('id'));
+ $service->store();
+ }
+
+ foreach ($this->fetchServices() as $service) {
+ if (!isset($seen[$service->getUniqueId()->getBytes()])) {
+ $service->delete();
+ }
+ }
+ }
+
+ /**
+ * @deprecated
* @return IcingaService[]
* @throws \Icinga\Exception\NotFoundError
*/
@@ -126,129 +206,9 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
return $this->getObjectName();
}
- /**
- * @return object
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
- {
- if ($this->get('host_id')) {
- $result = $this->exportSetOnHost();
- } else {
- $result = $this->exportTemplate();
- }
-
- unset($result->uuid);
- return $result;
- }
-
- protected function exportSetOnHost()
- {
- // TODO.
- throw new RuntimeException('Not yet');
- }
-
- /**
- * @return object
- * @deprecated
- * @throws \Icinga\Exception\NotFoundError
- */
- protected function exportTemplate()
- {
- $props = $this->getProperties();
- unset($props['id'], $props['host_id']);
- $props['services'] = [];
- foreach ($this->getServiceObjects() as $serviceObject) {
- $props['services'][$serviceObject->getObjectName()] = $serviceObject->export();
- }
- ksort($props);
-
- return (object) $props;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaServiceSet
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- $name = $properties['object_name'];
- if (isset($properties['services'])) {
- $services = $properties['services'];
- unset($properties['services']);
- } else {
- $services = [];
- }
-
- if ($properties['object_type'] !== 'template') {
- throw new InvalidArgumentException(sprintf(
- 'Can import only Templates, got "%s" for "%s"',
- $properties['object_type'],
- $name
- ));
- }
- if ($replace && static::exists($name, $db)) {
- $object = static::load($name, $db);
- } elseif (static::exists($name, $db)) {
- throw new DuplicateKeyException(
- 'Service Set "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- $object->setProperties($properties);
-
- // This is not how other imports work, but here we need an ID
- if (! $object->hasBeenLoadedFromDb()) {
- $object->store();
- }
-
- $setId = $object->get('id');
- $sQuery = $db->getDbAdapter()->select()->from(
- ['s' => 'icinga_service'],
- 's.*'
- )->where('service_set_id = ?', $setId);
- $existingServices = IcingaService::loadAll($db, $sQuery, 'object_name');
- $serviceNames = [];
- foreach ($services as $service) {
- if (isset($service->fields)) {
- unset($service->fields);
- }
- $name = $service->object_name;
- $serviceNames[] = $name;
- if (isset($existingServices[$name])) {
- $existing = $existingServices[$name];
- $existing->setProperties((array) $service);
- $existing->set('service_set_id', $setId);
- if ($existing->hasBeenModified()) {
- $existing->store();
- }
- } else {
- $new = IcingaService::create((array) $service, $db);
- $new->set('service_set_id', $setId);
- $new->store();
- }
- }
-
- foreach ($existingServices as $existing) {
- if (!in_array($existing->getObjectName(), $serviceNames)) {
- $existing->delete();
- }
- }
-
- return $object;
- }
-
public function beforeDelete()
{
+ $this->setCachedServices($this->getServices());
// check if this is a template, or directly assigned to a host
if ($this->get('host_id') === null) {
// find all host sets and delete them
@@ -295,8 +255,8 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
*/
public function renderToConfig(IcingaConfig $config)
{
- // always print the header, so you have minimal info present
- $file = $this->getConfigFileWithHeader($config);
+ $files = [];
+ $zone = $this->getRenderingZone($config) ;
if ($this->get('assign_filter') === null && $this->isTemplate()) {
return;
@@ -334,7 +294,15 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
}
$this->copyVarsToService($service);
- $file->addObject($service);
+ foreach ($service->getRenderingZones($config) as $serviceZone) {
+ $file = $this->getConfigFileWithHeader($config, $serviceZone, $files);
+ $file->addObject($service);
+ }
+ }
+
+ if (empty($files)) {
+ // always print the header, so you have minimal info present
+ $this->getConfigFileWithHeader($config, $zone, $files);
}
}
@@ -355,14 +323,18 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
return $lookup->getBlacklistedHostnamesForService($service);
}
- protected function getConfigFileWithHeader(IcingaConfig $config)
+ protected function getConfigFileWithHeader(IcingaConfig $config, $zone, &$files = [])
{
- $file = $config->configFile(
- 'zones.d/' . $this->getRenderingZone($config) . '/servicesets'
- );
+ if (!isset($files[$zone])) {
+ $file = $config->configFile(
+ 'zones.d/' . $zone . '/servicesets'
+ );
- $file->addContent($this->getConfigHeaderComment($config));
- return $file;
+ $file->addContent($this->getConfigHeaderComment($config));
+ $files[$zone] = $file;
+ }
+
+ return $files[$zone];
}
protected function getConfigHeaderComment(IcingaConfig $config)
@@ -372,13 +344,13 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
if ($config->isLegacy()) {
if ($assign !== null) {
- return "## applied Service Set '${name}'\n\n";
+ return "## applied Service Set '{$name}'\n\n";
} else {
- return "## Service Set '${name}' on this host\n\n";
+ return "## Service Set '{$name}' on this host\n\n";
}
} else {
$comment = [
- "Service Set: ${name}",
+ "Service Set: {$name}",
];
if (($host = $this->get('host')) !== null) {
@@ -505,7 +477,23 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
/**
* @return IcingaService[]
*/
- public function fetchServices()
+ public function getServices(): array
+ {
+ if ($this->services !== null) {
+ return $this->services;
+ }
+
+ if ($this->hasBeenLoadedFromDb()) {
+ return $this->fetchServices();
+ }
+
+ return [];
+ }
+
+ /**
+ * @return IcingaService[]
+ */
+ public function fetchServices(): array
{
if ($store = self::$dbObjectStore) {
$uuid = $store->getBranch()->getUuid();
@@ -569,6 +557,24 @@ class IcingaServiceSet extends IcingaObject implements ExportInterface
}
}
+ public function onStore()
+ {
+ $this->storeRelatedServices();
+ }
+
+ public function hasBeenModified()
+ {
+ if ($this->services !== null) {
+ foreach ($this->services as $service) {
+ if ($service->hasBeenModified()) {
+ return true;
+ }
+ }
+ }
+
+ return parent::hasBeenModified();
+ }
+
public function toSingleIcingaConfig()
{
$config = parent::toSingleIcingaConfig();
diff --git a/library/Director/Objects/IcingaTemplateChoice.php b/library/Director/Objects/IcingaTemplateChoice.php
index 1a1be90..a2be07a 100644
--- a/library/Director/Objects/IcingaTemplateChoice.php
+++ b/library/Director/Objects/IcingaTemplateChoice.php
@@ -3,9 +3,7 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Exception\ProgrammingError;
-use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\Web\Form\QuickForm;
class IcingaTemplateChoice extends IcingaObject implements ExportInterface
@@ -36,63 +34,6 @@ class IcingaTemplateChoice extends IcingaObject implements ExportInterface
return $this->getObjectName();
}
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaTemplateChoice
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- if (isset($properties['originalId'])) {
- unset($properties['originalId']);
- }
- $name = $properties['object_name'];
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Template Choice "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- $object->setProperties($properties);
-
- return $object;
- }
-
- /**
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @return array|object|\stdClass
- */
- public function export()
- {
- $plain = (object) $this->getProperties();
- $plain->originalId = $plain->id;
- unset($plain->id);
- $requiredId = $plain->required_template_id;
- unset($plain->required_template_id);
- if ($requiredId) {
- $db = $this->getDb();
- $query = $db->select()
- ->from(['o' => $this->getObjectTableName()], 'o.object_name')->where("o.object_type = 'template'")
- ->where('o.id = ?', $this->get('id'));
- $plain->required_template = $db->fetchOne($query);
- }
-
- $plain->members = array_values($this->getMembers());
-
- return $plain;
- }
-
public function isMainChoice()
{
return $this->hasBeenLoadedFromDb()
@@ -155,7 +96,7 @@ class IcingaTemplateChoice extends IcingaObject implements ExportInterface
public function hasBeenModified()
{
- if ($this->newChoices !== null && $this->choices !== $this->newChoices) {
+ if ($this->newChoices !== null && ($this->choices ?? $this->fetchChoices()) !== $this->newChoices) {
return true;
}
@@ -284,7 +225,7 @@ class IcingaTemplateChoice extends IcingaObject implements ExportInterface
} else {
throw new ProgrammingError(
'Expected array or null for allowed_roles, got %s',
- var_export($roles, 1)
+ var_export($roles, true)
);
}
}
diff --git a/library/Director/Objects/IcingaTemplateResolver.php b/library/Director/Objects/IcingaTemplateResolver.php
index 61122a0..7f14967 100644
--- a/library/Director/Objects/IcingaTemplateResolver.php
+++ b/library/Director/Objects/IcingaTemplateResolver.php
@@ -45,7 +45,6 @@ class IcingaTemplateResolver
{
$this->object = $object;
$this->type = $object->getShortTableName();
- $this->table = $object->getTableName();
$this->connection = $object->getConnection();
$this->db = $this->connection->getDbAdapter();
diff --git a/library/Director/Objects/IcingaTimePeriod.php b/library/Director/Objects/IcingaTimePeriod.php
index 1232366..081cdd9 100644
--- a/library/Director/Objects/IcingaTimePeriod.php
+++ b/library/Director/Objects/IcingaTimePeriod.php
@@ -2,9 +2,7 @@
namespace Icinga\Module\Director\Objects;
-use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
-use Icinga\Module\Director\Exception\DuplicateKeyException;
class IcingaTimePeriod extends IcingaObject implements ExportInterface
{
@@ -56,48 +54,6 @@ class IcingaTimePeriod extends IcingaObject implements ExportInterface
}
/**
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @return object
- * @throws \Icinga\Exception\NotFoundError
- */
- public function export()
- {
- $props = (array) $this->toPlainObject();
- ksort($props);
-
- return (object) $props;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return static
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- $name = $properties['object_name'];
- $key = $name;
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Time Period "%s" already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
- $object->setProperties($properties);
-
- return $object;
- }
-
- /**
* Render update property
*
* Avoid complaints for method names with underscore:
diff --git a/library/Director/Objects/IcingaUser.php b/library/Director/Objects/IcingaUser.php
index 394e849..4100245 100644
--- a/library/Director/Objects/IcingaUser.php
+++ b/library/Director/Objects/IcingaUser.php
@@ -48,43 +48,6 @@ class IcingaUser extends IcingaObject implements ExportInterface
'zone' => 'IcingaZone',
);
- public function export()
- {
- return ImportExportHelper::simpleExport($this);
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return IcingaUser
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- $key = $properties['object_name'];
-
- if ($replace && static::exists($key, $db)) {
- $object = static::load($key, $db);
- } elseif (static::exists($key, $db)) {
- throw new DuplicateKeyException(
- 'Cannot import, %s "%s" already exists',
- static::create([])->getShortTableName(),
- $key
- );
- } else {
- $object = static::create([], $db);
- }
-
- // $object->newFields = $properties['fields'];
- unset($properties['fields']);
- $object->setProperties($properties);
-
- return $object;
- }
-
public function getUniqueIdentifier()
{
return $this->getObjectName();
diff --git a/library/Director/Objects/ImportExportHelper.php b/library/Director/Objects/ImportExportHelper.php
deleted file mode 100644
index 98d34c6..0000000
--- a/library/Director/Objects/ImportExportHelper.php
+++ /dev/null
@@ -1,68 +0,0 @@
-<?php
-
-namespace Icinga\Module\Director\Objects;
-
-use Icinga\Module\Director\Db;
-
-/**
- * Helper class, allows to reduce duplicate code. Might be moved elsewhere
- * afterwards
- */
-class ImportExportHelper
-{
- /**
- * Does not support every type out of the box
- *
- * @param IcingaObject $object
- * @return object
- * @throws \Icinga\Exception\NotFoundError
- */
- public static function simpleExport(IcingaObject $object)
- {
- $props = (array) $object->toPlainObject();
- $props['fields'] = static::fetchFields($object);
- ksort($props); // TODO: ksort in toPlainObject?
-
- return (object) $props;
- }
-
- public static function fetchFields(IcingaObject $object)
- {
- return static::loadFieldReferences(
- $object->getConnection(),
- $object->getShortTableName(),
- $object->get('id')
- );
- }
-
- /**
- * @param Db $connection
- * @param string $type Warning: this will not be validated.
- * @param int $id
- * @return array
- */
- public static function loadFieldReferences(Db $connection, $type, $id)
- {
- $db = $connection->getDbAdapter();
- $res = $db->fetchAll(
- $db->select()->from([
- 'f' => "icinga_${type}_field"
- ], [
- 'f.datafield_id',
- 'f.is_required',
- 'f.var_filter',
- ])->join(['df' => 'director_datafield'], 'df.id = f.datafield_id', [])
- ->where("${type}_id = ?", $id)
- ->order('varname ASC')
- );
-
- if (empty($res)) {
- return [];
- }
-
- foreach ($res as $field) {
- $field->datafield_id = (int) $field->datafield_id;
- }
- return $res;
- }
-}
diff --git a/library/Director/Objects/ImportRowModifier.php b/library/Director/Objects/ImportRowModifier.php
index 76982c2..afebbad 100644
--- a/library/Director/Objects/ImportRowModifier.php
+++ b/library/Director/Objects/ImportRowModifier.php
@@ -18,13 +18,14 @@ class ImportRowModifier extends DbObjectWithSettings implements InstantiatedViaH
protected $autoincKeyName = 'id';
protected $defaultProperties = [
- 'id' => null,
- 'source_id' => null,
- 'property_name' => null,
- 'provider_class' => null,
- 'target_property' => null,
- 'priority' => null,
- 'description' => null,
+ 'id' => null,
+ 'source_id' => null,
+ 'property_name' => null,
+ 'provider_class' => null,
+ 'target_property' => null,
+ 'filter_expression' => null,
+ 'priority' => null,
+ 'description' => null,
];
protected $settingsTable = 'import_row_modifier_setting';
diff --git a/library/Director/Objects/ImportSource.php b/library/Director/Objects/ImportSource.php
index fd892ef..7477472 100644
--- a/library/Director/Objects/ImportSource.php
+++ b/library/Director/Objects/ImportSource.php
@@ -3,12 +3,14 @@
namespace Icinga\Module\Director\Objects;
use Icinga\Application\Benchmark;
+use Icinga\Data\Filter\Filter;
use Icinga\Exception\NotFoundError;
use Icinga\Module\Director\Application\MemoryLimit;
use Icinga\Module\Director\Data\Db\DbObjectWithSettings;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
use Icinga\Module\Director\Exception\DuplicateKeyException;
+use Icinga\Module\Director\Filter\FilterEnrichment;
use Icinga\Module\Director\Hook\PropertyModifierHook;
use Icinga\Module\Director\Import\Import;
use Icinga\Module\Director\Import\SyncUtils;
@@ -52,68 +54,6 @@ class ImportSource extends DbObjectWithSettings implements ExportInterface
private $newRowModifiers;
- /**
- * @deprecated please use \Icinga\Module\Director\Data\FieldReferenceLoader
- * @return \stdClass
- */
- public function export()
- {
- $plain = $this->getProperties();
- $plain['originalId'] = $plain['id'];
- unset($plain['id']);
-
- foreach ($this->stateProperties as $key) {
- unset($plain[$key]);
- }
-
- $plain['settings'] = (object) $this->getSettings();
- $plain['modifiers'] = $this->exportRowModifiers();
- ksort($plain);
-
- return (object) $plain;
- }
-
- /**
- * @param $plain
- * @param Db $db
- * @param bool $replace
- * @return ImportSource
- * @throws DuplicateKeyException
- * @throws NotFoundError
- */
- public static function import($plain, Db $db, $replace = false)
- {
- $properties = (array) $plain;
- if (isset($properties['originalId'])) {
- $id = $properties['originalId'];
- unset($properties['originalId']);
- } else {
- $id = null;
- }
- $name = $properties['source_name'];
-
- if ($replace && $id && static::existsWithNameAndId($name, $id, $db)) {
- $object = static::loadWithAutoIncId($id, $db);
- } elseif ($replace && static::exists($name, $db)) {
- $object = static::load($name, $db);
- } elseif (static::existsWithName($name, $db)) {
- throw new DuplicateKeyException(
- 'Import Source %s already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- if (! isset($properties['modifiers'])) {
- $properties['modifiers'] = [];
- }
-
- $object->setProperties($properties);
-
- return $object;
- }
-
public function setModifiers(array $modifiers)
{
if ($this->loadedRowModifiers === null && $this->hasBeenLoadedFromDb()) {
@@ -314,10 +254,14 @@ class ImportSource extends DbObjectWithSettings implements ExportInterface
foreach ($modifiers as $modPair) {
/** @var PropertyModifierHook $modifier */
- list($property, $modifier) = $modPair;
+ /** @var ?Filter $filter */
+ list($property, $modifier, $filter) = $modPair;
$rejected = [];
$newRows = [];
foreach ($data as $key => $row) {
+ if ($filter && ! $filter->matches($row)) {
+ continue;
+ }
$this->applyPropertyModifierToRow($modifier, $property, $row);
if ($modifier->rejectsRow()) {
$rejected[] = $key;
@@ -434,7 +378,12 @@ class ImportSource extends DbObjectWithSettings implements ExportInterface
{
$mods = [];
foreach ($this->fetchRowModifiers() as $mod) {
- $mods[] = [$mod->get('property_name'), $mod->getInstance()];
+ if ($filterExpression = $mod->get('filter_expression')) {
+ $filter = FilterEnrichment::enrichFilter(Filter::fromQueryString($filterExpression));
+ } else {
+ $filter = null;
+ }
+ $mods[] = [$mod->get('property_name'), $mod->getInstance(), $filter];
}
return $mods;
@@ -530,7 +479,7 @@ class ImportSource extends DbObjectWithSettings implements ExportInterface
protected function raiseLimits()
{
MemoryLimit::raiseTo('1024M');
- ini_set('max_execution_time', 0);
+ ini_set('max_execution_time', '0');
return $this;
}
diff --git a/library/Director/Objects/ObjectApplyMatches.php b/library/Director/Objects/ObjectApplyMatches.php
index 018c880..d749d6a 100644
--- a/library/Director/Objects/ObjectApplyMatches.php
+++ b/library/Director/Objects/ObjectApplyMatches.php
@@ -172,7 +172,7 @@ abstract class ObjectApplyMatches
$col = $filter->getColumn();
$type = static::$type;
- if ($type && substr($col, 0, strlen($type) + 1) === "${type}.") {
+ if ($type && substr($col, 0, strlen($type) + 1) === "{$type}.") {
$filter->setColumn($col = substr($col, strlen($type) + 1));
}
diff --git a/library/Director/Objects/SyncRule.php b/library/Director/Objects/SyncRule.php
index 89f7fd1..270a882 100644
--- a/library/Director/Objects/SyncRule.php
+++ b/library/Director/Objects/SyncRule.php
@@ -43,6 +43,10 @@ class SyncRule extends DbObject implements ExportInterface
'last_attempt',
];
+ protected $booleans = [
+ 'purge_existing' => 'purge_existing',
+ ];
+
private $sync;
private $purgeStrategy;
@@ -60,8 +64,6 @@ class SyncRule extends DbObject implements ExportInterface
private $newSyncProperties;
- private $originalId;
-
public function listInvolvedSourceIds()
{
if (! $this->hasBeenLoadedFromDb()) {
@@ -257,61 +259,13 @@ class SyncRule extends DbObject implements ExportInterface
}
/**
- * @deprecated please use \Icinga\Module\Director\Data\Exporter
- * @return object
- */
- public function export()
- {
- $plain = $this->getProperties();
- $plain['originalId'] = $plain['id'];
- unset($plain['id']);
-
- foreach ($this->stateProperties as $key) {
- unset($plain[$key]);
- }
- $plain['properties'] = $this->exportSyncProperties();
- ksort($plain);
-
- return (object) $plain;
- }
-
- /**
- * @param object $plain
- * @param Db $db
- * @param bool $replace
- * @return static
- * @throws DuplicateKeyException
- * @throws \Icinga\Exception\NotFoundError
+ * Flat object has 'properties', but setProperties() is not available in DbObject
+ *
+ * @return void
*/
- public static function import($plain, Db $db, $replace = false)
+ public function setSyncProperties(?array $value)
{
- $properties = (array) $plain;
- if (isset($properties['originalId'])) {
- $id = $properties['originalId'];
- unset($properties['originalId']);
- } else {
- $id = null;
- }
- $name = $properties['rule_name'];
-
- if ($replace && $id && static::existsWithNameAndId($name, $id, $db)) {
- $object = static::loadWithAutoIncId($id, $db);
- } elseif ($replace && static::exists($name, $db)) {
- $object = static::load($name, $db);
- } elseif (static::existsWithName($name, $db)) {
- throw new DuplicateKeyException(
- 'Sync Rule %s already exists',
- $name
- );
- } else {
- $object = static::create([], $db);
- }
-
- $object->newSyncProperties = $properties['properties'];
- unset($properties['properties']);
- $object->setProperties($properties);
-
- return $object;
+ $this->newSyncProperties = $value;
}
public function getUniqueIdentifier()
@@ -329,12 +283,6 @@ class SyncRule extends DbObject implements ExportInterface
$connection = $this->getConnection();
$db = $connection->getDbAdapter();
$myId = $this->get('id');
- if ($this->originalId === null) {
- $originalId = $myId;
- } else {
- $originalId = $this->originalId;
- $this->originalId = null;
- }
if ($this->hasBeenLoadedFromDb()) {
$db->delete(
'sync_property',