Add postgres support

This commit is contained in:
Ravi Srinivasa 2026-03-25 17:03:21 +01:00
parent 19a648e8a9
commit dcb77a1573
No known key found for this signature in database
13 changed files with 477 additions and 64 deletions

View file

@ -69,7 +69,9 @@ class CustomvarController extends CompatController
$parent = $this->fetchProperty($parentUuid);
if ($parent['parent_uuid'] !== null) {
$usedCount = $this->fetchPropertyUsedCount(Uuid::fromBytes($parent['parent_uuid']));
$usedCount = $this->fetchPropertyUsedCount(Uuid::fromBytes(
Db\DbUtil::binaryResult($parent['parent_uuid'])
));
} else {
$usedCount = $this->fetchPropertyUsedCount($parentUuid);
}
@ -84,7 +86,7 @@ class CustomvarController extends CompatController
->select()->from('director_property', 'value_type')
->where(
'parent_uuid = ? AND key_name = \'0\'',
$uuid->getBytes()
Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db)
);
$property['item_type'] = $db->fetchOne($itemTypeQuery);
@ -96,7 +98,7 @@ class CustomvarController extends CompatController
->join(['dpl' => 'director_property_datalist'], 'dpl.list_uuid = dl.uuid', [])
->where(
'dpl.property_uuid = ?',
$uuid->getBytes()
Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db)
);
$property['list'] = $db->fetchOne($datalistId);
@ -162,7 +164,7 @@ class CustomvarController extends CompatController
'description',
'used_count' => $property['used_count'] > 0 ? 'COUNT(1)' : '0',
])
->where('parent_uuid = ?', $uuid->getBytes())
->where('parent_uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db))
->group('dp.uuid')
->order('key_name');
@ -233,12 +235,13 @@ class CustomvarController extends CompatController
{
$uuid = $this->uuid;
$property = $this->fetchProperty($uuid);
$db = $this->db->getDbAdapter();
if (isset($property['parent_uuid'])) {
$parentUuid = Uuid::fromBytes($property['parent_uuid']);
$parentUuid = Uuid::fromBytes(Db\DbUtil::binaryResult($property['parent_uuid']));
$this->parentUuid = $parentUuid;
$parentProperty = $this->fetchProperty($parentUuid);
if (isset($parentProperty['parent_uuid'])) {
$rootUuid = Uuid::fromBytes($parentProperty['parent_uuid']);
$rootUuid = Uuid::fromBytes(Db\DbUtil::binaryResult($parentProperty['parent_uuid']));
} else {
$rootUuid = $parentUuid;
}
@ -246,7 +249,6 @@ class CustomvarController extends CompatController
$uuid = $rootUuid;
}
$db = $this->db->getDbAdapter();
$objectClasses = ['host', 'service', 'notification', 'command', 'user'];
$usage = [];
@ -279,11 +281,13 @@ class CustomvarController extends CompatController
$columns['host_name'] = 'ioh.object_name';
}
$customPropertyQuery = $customPropertyQuery->columns($columns)
->where('dp.uuid = ?', $uuid->getBytes());
$customPropertyQuery = $customPropertyQuery
->columns($columns)
->where('dp.uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
$unionQuery = $unionQuery->columns($columns)
->where('dp.uuid = ?', $uuid->getBytes());
$unionQuery = $unionQuery
->columns($columns)
->where('dp.uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
$usage[] = $db->fetchAll($db->select()->union([$customPropertyQuery, $unionQuery]));
}
@ -379,7 +383,7 @@ class CustomvarController extends CompatController
'label',
'description'
])
->where('uuid = ?', $uuid->getBytes());
->where('uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
return $db->fetchRow($query, [], Zend_Db::FETCH_ASSOC) ?: [];
}
@ -401,7 +405,7 @@ class CustomvarController extends CompatController
. ' + COUNT(iup.property_uuid) + COUNT(icp.property_uuid)'
. ' + COUNT(inp.property_uuid)'
])
->where('uuid = ?', $uuid->getBytes());
->where('uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
return (int) $db->fetchOne($query);
}

View file

@ -5,6 +5,7 @@ namespace Icinga\Module\Director\Forms;
use Icinga\Data\Filter\Filter;
use Icinga\Data\Filter\FilterException;
use Icinga\Module\Director\Data\Db\DbConnection;
use Icinga\Module\Director\Db;
use Icinga\Web\Session;
use ipl\I18n\Translation;
use ipl\Web\Common\CsrfCounterMeasure;
@ -95,7 +96,7 @@ class CustomVariableForm extends CompatForm
$db = $this->db->getDbAdapter();
$query = $db->select()
->from('director_property', ['count' => 'COUNT(*)'])
->where('parent_uuid = ?', $this->parentUuid->getBytes());
->where('parent_uuid = ?', Db\DbUtil::quoteBinaryCompat($this->parentUuid->getBytes(), $db));
$this->addElement(
'hidden',
@ -314,7 +315,7 @@ class CustomVariableForm extends CompatForm
'label',
'description'
])
->where('uuid = ?', $uuid->getBytes());
->where('uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
return $db->fetchRow($query, [], Zend_Db::FETCH_ASSOC);
}
@ -388,27 +389,29 @@ class CustomVariableForm extends CompatForm
string $itemType = ''
): void {
$this->uuid = Uuid::uuid4();
$quotedUuid = Db\DbUtil::quoteBinaryCompat($this->uuid->getBytes(), $this->db->getDbAdapter());
$dynamicArrayItemType = [];
if ($itemType !== '') {
$dynamicArrayItemType = [
'uuid' => Uuid::uuid4()->getBytes(),
'uuid' => Db\DbUtil::quoteBinaryCompat(Uuid::uuid4()->getBytes(), $this->db->getDbAdapter()),
'key_name' => '0',
'value_type' => $itemType,
'parent_uuid' => $this->uuid->getBytes()
'parent_uuid' => $quotedUuid
];
}
if ($this->field) {
$quotedParentUuid = Db\DbUtil::quoteBinaryCompat($this->parentUuid->getBytes(), $this->db->getDbAdapter());
$values = array_merge(
[
'uuid' => $this->uuid->getBytes(),
'parent_uuid' => $this->parentUuid->getBytes()
'uuid' => $quotedUuid,
'parent_uuid' => $quotedParentUuid
],
$values
);
} else {
$values = array_merge(
['uuid' => $this->uuid->getBytes()],
['uuid' => $quotedUuid],
$values
);
}
@ -421,8 +424,8 @@ class CustomVariableForm extends CompatForm
if (! empty($datalist)) {
$this->db->insert('director_property_datalist', [
'property_uuid' => $this->uuid->getBytes(),
'list_uuid' => $datalist['uuid'],
'property_uuid' => $quotedUuid,
'list_uuid' => Db\DbUtil::quoteBinaryCompat($datalist['uuid'], $this->db->getDbAdapter()),
]);
}
}
@ -460,27 +463,36 @@ class CustomVariableForm extends CompatForm
) {
$this->db->delete(
'director_property',
Filter::matchAll(Filter::where('parent_uuid', $this->uuid->getBytes()))
Filter::matchAll(Filter::where(
'parent_uuid',
Db\DbUtil::quoteBinaryCompat($this->uuid->getBytes(), $this->db->getDbAdapter())
))
);
$this->db->delete(
'director_property_datalist',
Filter::matchAll(Filter::where('property_uuid', $this->uuid->getBytes()))
Filter::matchAll(Filter::where(
'property_uuid',
Db\DbUtil::quoteBinaryCompat($this->uuid->getBytes(), $this->db->getDbAdapter())
))
);
}
if ($itemType && ($valueType === 'dynamic-array' || str_starts_with($valueType, 'datalist-'))) {
$this->db->insert('director_property', [
'uuid' => Uuid::uuid4()->getBytes(),
'uuid' => Db\DbUtil::quoteBinaryCompat(Uuid::uuid4()->getBytes(), $this->db->getDbAdapter()),
'key_name' => '0',
'value_type' => $itemType,
'parent_uuid' => $this->uuid->getBytes()
'parent_uuid' => Db\DbUtil::quoteBinaryCompat($this->uuid->getBytes(), $this->db->getDbAdapter()),
]);
if (str_starts_with($valueType, 'datalist-')) {
$this->db->insert('director_property_datalist', [
'property_uuid' => $this->uuid->getBytes(),
'list_uuid' => $datalist['uuid'],
'property_uuid' => Db\DbUtil::quoteBinaryCompat(
$this->uuid->getBytes(),
$this->db->getDbAdapter()
),
'list_uuid' => Db\DbUtil::quoteBinaryCompat($datalist['uuid'], $this->db->getDbAdapter()),
]);
}
}
@ -488,7 +500,7 @@ class CustomVariableForm extends CompatForm
$storedKeyName = $this->db->fetchOne(
$this->db->select()
->from('director_property', ['key_name'])
->where('uuid', $this->uuid->getBytes())
->where('uuid', Db\DbUtil::quoteBinaryCompat($this->uuid->getBytes(), $this->db->getDbAdapter()))
);
if ($storedKeyName !== $values['key_name']) {
@ -499,7 +511,7 @@ class CustomVariableForm extends CompatForm
$this->db->update(
'director_property',
$values,
Filter::where('uuid', $this->uuid->getBytes())
Filter::where('uuid', Db\DbUtil::quoteBinaryCompat($this->uuid->getBytes(), $this->db->getDbAdapter()))
);
}
@ -540,7 +552,7 @@ class CustomVariableForm extends CompatForm
'varvalue',
'property_uuid'
])
->where('property_uuid = ?', $rootUuid->getBytes()),
->where('property_uuid = ?', Db\DbUtil::quoteBinaryCompat($rootUuid->getBytes(), $db)),
[],
PDO::FETCH_ASSOC
);
@ -551,7 +563,7 @@ class CustomVariableForm extends CompatForm
"icinga_{$objectType}_var",
['varname' => $keyName],
Filter::matchAll(
Filter::where('property_uuid', $rootUuid->getBytes()),
Filter::where('property_uuid', Db\DbUtil::quoteBinaryCompat($rootUuid->getBytes(), $db)),
Filter::where("{$objectType}_id", $objectCustomVar["{$objectType}_id"])
)
);
@ -585,7 +597,7 @@ class CustomVariableForm extends CompatForm
"icinga_{$objectType}_var",
['varvalue' => json_encode($varValue)],
Filter::matchAll(
Filter::where('property_uuid', $rootUuid->getBytes()),
Filter::where('property_uuid', Db\DbUtil::quoteBinaryCompat($rootUuid->getBytes(), $db)),
Filter::where("{$objectType}_id", $objectCustomVar["{$objectType}_id"])
)
);

View file

@ -3,6 +3,7 @@
namespace Icinga\Module\Director\Forms;
use Icinga\Module\Director\Data\Db\DbObjectTypeRegistry;
use Icinga\Module\Director\Db\DbUtil;
use Icinga\Module\Director\Forms\DictionaryElements\Dictionary;
use Icinga\Module\Director\Objects\DirectorActivityLog;
use Icinga\Module\Director\Objects\IcingaHost;
@ -215,6 +216,7 @@ class CustomVariablesForm extends CompatForm
$values = $propertiesElement->getDictionary();
$itemsToRemove = $propertiesElement->getItemsToRemove();
$type = $this->object->getShortTableName();
$db = $this->object->getDb();
foreach ($this->objectProperties as $key => $property) {
$propertyUuid = Uuid::fromBytes($property['uuid']);
if (isset($property['removed'])) {
@ -243,8 +245,8 @@ class CustomVariablesForm extends CompatForm
$this->object->getConnection()->insert(
"icinga_$type" . '_property',
[
$type . '_uuid' => $this->object->uuid,
'property_uuid' => $propertyUuid->getBytes()
$type . '_uuid' => DbUtil::quoteBinaryCompat($this->object->uuid, $db),
'property_uuid' => DbUtil::quoteBinaryCompat($propertyUuid->getBytes(), $db)
]
);
}
@ -273,7 +275,7 @@ class CustomVariablesForm extends CompatForm
$db
->select()
->from('icinga_' . $type . '_var')
->where('property_uuid IN (?)', $itemsToRemoveUuids)
->where('property_uuid IN (?)', DbUtil::quoteBinaryCompat($itemsToRemoveUuids, $db))
);
foreach ($propertyAsObjectVar as $propertyAsObjectVarRow) {

View file

@ -2,6 +2,7 @@
namespace Icinga\Module\Director\Forms\DictionaryElements;
use Icinga\Module\Director\Db\DbUtil;
use Icinga\Web\Session;
use ipl\Html\FormElement\FieldsetElement;
use ipl\Web\Widget\EmptyStateBar;
@ -104,6 +105,11 @@ class Dictionary extends FieldsetElement
$this->addElement('hidden', 'items_added', ['value' => implode(', ', $addedItems)]);
$count = 0;
foreach ($this->items as $item) {
$item['uuid'] = DbUtil::binaryResult($item['uuid']);
if (isset($item['parent_uuid'])) {
$item['parent_uuid'] = DbUtil::binaryResult($item['parent_uuid']);
}
$element = new DictionaryItem($count, $item);
// Only allow removal of items if the dictionary allows it and the item allows it

View file

@ -4,6 +4,7 @@ namespace Icinga\Module\Director\Forms\DictionaryElements;
use Icinga\Application\Config;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Db\DbUtil;
use Icinga\Module\Director\Forms\Validator\DatalistEntryValidator;
use Icinga\Module\Director\Web\Form\Element\ArrayElement;
use Icinga\Module\Director\Web\Form\Element\IplBoolean;
@ -48,7 +49,8 @@ class DictionaryItem extends FieldsetElement
['dp' => 'director_property'],
['value_type' => 'dp.value_type']
)
->where('dp.parent_uuid = ?', $uuid->getBytes());
->where('dp.parent_uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
return $db->fetchOne($query);
}
@ -69,7 +71,7 @@ class DictionaryItem extends FieldsetElement
)
->join(['dl' => 'director_datalist'], 'dl.id = dle.list_id', [])
->join(['dpl' => 'director_property_datalist'], 'dl.uuid = dpl.list_uuid', [])
->where('dpl.property_uuid = ?', $uuid->getBytes());
->where('dpl.property_uuid = ?', Db\DbUtil::quoteBinaryCompat($uuid->getBytes(), $db));
return $db->fetchPairs($query);
}
@ -78,7 +80,7 @@ class DictionaryItem extends FieldsetElement
{
$this->addElement('hidden', 'name', ['value' => $this->fields['key_name'] ?? '']);
$this->addElement('hidden', 'type', ['value' => $this->fields['value_type'] ?? '']);
$this->addElement('hidden', 'label', ['value' => $this->fields['key_name'] ?? '']);
$this->addElement('hidden', 'label', ['value' => $this->fields['label'] ?? '']);
$this->addElement('hidden', 'parent_type', ['value' => $this->fields['parent_type'] ?? '']);
$this->addElement('hidden', 'inherited');
@ -280,6 +282,8 @@ class DictionaryItem extends FieldsetElement
'parent_type' => $property['parent_type'] ?? ''
];
$property['uuid'] = Dbutil::binaryResult($property['uuid'] ?? '');
if (
$property['value_type'] === 'dynamic-array'
|| (
@ -373,7 +377,7 @@ class DictionaryItem extends FieldsetElement
'children' => 'COUNT(cdp.uuid)'
]
)
->where('dp.parent_uuid = ?', $parentUuid->getBytes())
->where('dp.parent_uuid = ?', Db\DbUtil::quoteBinaryCompat($parentUuid->getBytes(), $db))
->joinLeft(
['cdp' => 'director_property'],
'cdp.parent_uuid = dp.uuid',
@ -384,6 +388,12 @@ class DictionaryItem extends FieldsetElement
->order('key_name');
$propertyItems = $db->fetchAll($query, fetchMode: PDO::FETCH_ASSOC);
foreach ($propertyItems as $key => $propertyItem) {
$propertyItem['uuid'] = DbUtil::binaryResult($propertyItem['uuid']);
$propertyItem['parent_uuid'] = DbUtil::binaryResult($propertyItem['parent_uuid']);
$propertyItems[$key] = $propertyItem;
}
if (empty($values)) {
return $propertyItems;
}

View file

@ -103,7 +103,8 @@ class ObjectCustomvarForm extends CompatForm
->getNamespace('director.variables')->get('added-properties', []);
foreach ($properties as $property) {
if (! isset($alreadyAddedProperties[$property->key_name])) {
$propUuidKeyPairs[Uuid::fromBytes($property->uuid)->toString()] = $property->key_name;
$uuid = DbUtil::binaryResult($property->uuid);
$propUuidKeyPairs[Uuid::fromBytes($uuid)->toString()] = $property->key_name;
}
}

View file

@ -4,6 +4,7 @@ namespace Icinga\Module\Director\CustomVariable;
use Exception;
use Icinga\Module\Director\Db\Cache\PrefetchCache;
use Icinga\Module\Director\Db\DbUtil;
use Icinga\Module\Director\IcingaConfig\IcingaConfigHelper as c;
use Icinga\Module\Director\IcingaConfig\IcingaConfigRenderer;
use InvalidArgumentException;
@ -309,7 +310,7 @@ abstract class CustomVariable implements IcingaConfigRenderer
}
if (property_exists($row, 'property_uuid') && $row->property_uuid) {
$var->setUuid(Uuid::fromBytes($row->property_uuid));
$var->setUuid(Uuid::fromBytes(DbUtil::binaryResult($row->property_uuid)));
}
$var->loadedFromDb = true;

View file

@ -246,7 +246,7 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer
];
if ($uuid) {
$row['property_uuid'] = $uuid;
$row['property_uuid'] = Db\DbUtil::quoteBinaryCompat($uuid, $db);
}
$db->insert($table, $row);
@ -267,7 +267,7 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer
];
if ($object->getShortTableName() === 'host' && $uuid) {
$data['property_uuid'] = $uuid;
$data['property_uuid'] = Db\DbUtil::quoteBinaryCompat($uuid, $db);
}
$db->update(

View file

@ -9,6 +9,7 @@ use Icinga\Exception\ProgrammingError;
use Icinga\Module\Director\Core\CoreApi;
use Icinga\Module\Director\CustomVariable\CustomVariables;
use Icinga\Module\Director\Data\Exporter;
use Icinga\Module\Director\Db\DbUtil;
use Icinga\Module\Director\DirectorObject\Lookup\ServiceFinder;
use Icinga\Module\Director\Exception\DuplicateKeyException;
use Icinga\Module\Director\Objects\IcingaHost;
@ -253,7 +254,7 @@ class IcingaObjectHandler extends RequestHandler
$objectPropertyWhere = $db->getDbAdapter()->quoteInto(
"{$type}_uuid = ?",
Uuid::fromBytes($this->object->get('uuid'))->getBytes()
Uuid::fromBytes(DbUtil::binaryResult($this->object->get('uuid')))->getBytes()
);
$db->getDbAdapter()->delete(
'icinga_' . $type . '_property',
@ -312,7 +313,7 @@ class IcingaObjectHandler extends RequestHandler
'icinga_' . $type . '_property',
[
'property_uuid' => $customPropertyUuid,
$type . '_uuid' => $object->get('uuid')
$type . '_uuid' => DbUtil::quoteBinaryCompat($object->get('uuid'), $db->getDbAdapter())
]
);

View file

@ -8,10 +8,12 @@ use Icinga\Exception\InvalidPropertyException;
use Icinga\Exception\NotFoundError;
use Icinga\Exception\ProgrammingError;
use Icinga\Module\Director\Dashboard\Dashlet\DeploymentDashlet;
use Icinga\Module\Director\Data\Db\DbConnection;
use Icinga\Module\Director\Data\Db\DbObjectTypeRegistry;
use Icinga\Module\Director\Db\Branch\Branch;
use Icinga\Module\Director\Db\Branch\BranchedObject;
use Icinga\Module\Director\Db\Branch\UuidLookup;
use Icinga\Module\Director\Db\DbUtil;
use Icinga\Module\Director\Deployment\DeploymentInfo;
use Icinga\Module\Director\DirectorObject\Automation\ExportInterface;
use Icinga\Module\Director\Exception\NestingError;
@ -652,7 +654,7 @@ abstract class ObjectController extends ActionController
'label' => 'dp.label',
'value_type' => 'dp.value_type'
]
)->where("parent_uuid = ?", $dictionaryUuid);
)->where("parent_uuid = ?", DbUtil::quoteBinaryCompat($dictionaryUuid, $db->getDbAdapter()));
return $db->getDbAdapter()->fetchAll($query, fetchMode: PDO::FETCH_ASSOC);
}
@ -670,6 +672,19 @@ abstract class ObjectController extends ActionController
return $db->getDbAdapter()->fetchRow($query);
}
private function valueTypeOrderExpr(DbConnection $db, array $types): string
{
if ($db->isPgsql()) {
$cases = [];
foreach ($types as $i => $type) {
$cases[] = "WHEN '$type' THEN " . ($i + 1);
}
return 'CASE dp.value_type ' . implode(' ', $cases) . ' ELSE ' . (count($types) + 1) . ' END';
}
return "FIELD(dp.value_type, '" . implode("', '", $types) . "')";
}
/**
* Get custom properties for the host.
*
@ -687,11 +702,14 @@ abstract class ObjectController extends ActionController
$uuids = [];
$db = $this->db();
foreach ($parents as $parent) {
$uuids[] = IcingaObject::loadByType($type, $parent, $db)->get('uuid');
$uuids[] = DbUtil::quoteBinaryCompat(
IcingaObject::loadByType($type, $parent, $db)->get('uuid'),
$db->getDbAdapter()
);
}
$objectUuid = $object->get('uuid');
$uuids[] = $object->get('uuid');
$uuids[] = Dbutil::quoteBinaryCompat($objectUuid, $db->getDbAdapter());
$query = $db->getDbAdapter()
->select()
->from(
@ -716,11 +734,17 @@ abstract class ObjectController extends ActionController
[]
)
->where('iop.' . $type . '_uuid IN (?)', $uuids)
->group(['dp.uuid', 'dp.key_name', 'dp.value_type', 'dp.label'])
->order(
"FIELD(dp.value_type, 'string', 'number', 'bool', 'datalist-strict', 'datalist-non-strict',"
. " 'dynamic-array', 'fixed-dictionary', 'dynamic-dictionary')"
)
->group(['dp.uuid', 'dp.key_name', 'dp.value_type', 'dp.label', $type . '_uuid'])
->order($this->valueTypeOrderExpr($db, [
'string',
'number',
'bool',
'datalist-strict',
'datalist-non-strict',
'dynamic-array',
'fixed-dictionary',
'dynamic-dictionary'
]))
->order('children')
->order('key_name');
@ -739,6 +763,8 @@ abstract class ObjectController extends ActionController
}
foreach ($db->getDbAdapter()->fetchAll($query, fetchMode: PDO::FETCH_ASSOC) as $row) {
$row['uuid'] = DbUtil::binaryResult($row['uuid']);
$row[$type . '_uuid'] = DbUtil::binaryResult($row[$type . '_uuid']);
if ($objectUuid === $row[$type . '_uuid']) {
$row['allow_removal'] = true;
} else {
@ -775,18 +801,19 @@ abstract class ObjectController extends ActionController
'cdp.parent_uuid = dp.uuid',
[]
)
->where('dp.' . 'uuid IN (?)', $addedProperties)
->where('dp.' . 'uuid IN (?)', DbUtil::quoteBinaryCompat($addedProperties, $db->getDbAdapter()))
->group(['dp.uuid', 'dp.key_name', 'dp.value_type', 'dp.label'])
->order(
"FIELD(dp.value_type, 'string', 'number', 'bool', 'datalist-strict', 'datalist-non-strict',"
. " 'dynamic-array', 'fixed-array', 'fixed-dictionary', 'dynamic-dictionary')"
)
->order($this->valueTypeOrderExpr($db, [
'string', 'number', 'bool', 'datalist-strict', 'datalist-non-strict',
'dynamic-array', 'fixed-array', 'fixed-dictionary', 'dynamic-dictionary'
]))
->order('children')
->order('key_name');
foreach ($db->getDbAdapter()->fetchAll($query, fetchMode: PDO::FETCH_ASSOC) as $row) {
$row['allow_removal'] = true;
$row['host_uuid'] = $this->object->get('uuid');
$row['host_uuid'] = DbUtil::binaryResult($this->object->get('uuid'));
$row['uuid'] = DbUtil::binaryResult($row['uuid']);
if (! isset($result[$row['key_name']])) {
$row['new'] = true;
}

View file

@ -2,6 +2,7 @@
namespace Icinga\Module\Director\Web\Widget;
use Icinga\Module\Director\Db\DbUtil;
use ipl\Html\HtmlElement;
use ipl\Html\Table;
use ipl\I18n\Translation;
@ -27,13 +28,15 @@ class CustomVarFieldsTable extends Table
protected function assemble()
{
foreach ($this->properties as $property) {
$propertyUuid = DbUtil::binaryResult($property->uuid);
$url = Url::fromPath(
'director/customvar',
['uuid' => Uuid::fromBytes($property->uuid)->toString()]
['uuid' => Uuid::fromBytes($propertyUuid)->toString()]
);
if (isset($property->parent_uuid)) {
$url->addParams(['parent_uuid' => Uuid::fromBytes($property->parent_uuid)->toString()]);
$parentUuid = DbUtil::binaryResult($property->parent_uuid);
$url->addParams(['parent_uuid' => Uuid::fromBytes($parentUuid)->toString()]);
}
$columns = [

View file

@ -0,0 +1,180 @@
CREATE TYPE enum_property_value_type AS ENUM(
'string',
'number',
'bool',
'fixed-array',
'dynamic-array',
'fixed-dictionary',
'dynamic-dictionary',
'datalist-strict',
'datalist-non-strict'
);
CREATE TABLE director_property (
uuid bytea CHECK(LENGTH(uuid) = 16) NOT NULL,
parent_uuid bytea CHECK(LENGTH(parent_uuid) = 16) DEFAULT NULL,
key_name character varying(255) NOT NULL,
label character varying(255) DEFAULT NULL,
description text DEFAULT NULL,
value_type enum_property_value_type NOT NULL,
category_id integer DEFAULT NULL,
PRIMARY KEY (uuid),
CONSTRAINT director_property_category
FOREIGN KEY (category_id)
REFERENCES director_datafield_category (id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
-- Unique key_name at root level (no parent)
CREATE UNIQUE INDEX unique_property_name_root
ON director_property (key_name)
WHERE parent_uuid IS NULL;
-- Unique (key_name, parent_uuid) for nested properties
CREATE UNIQUE INDEX unique_property_name_parent
ON director_property (key_name, parent_uuid)
WHERE parent_uuid IS NOT NULL;
CREATE TABLE icinga_host_property (
host_uuid bytea CHECK(LENGTH(host_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (host_uuid, property_uuid),
CONSTRAINT icinga_host_property_host
FOREIGN KEY (host_uuid)
REFERENCES icinga_host (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_host_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_service_property (
service_uuid bytea CHECK(LENGTH(service_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (service_uuid, property_uuid),
CONSTRAINT icinga_service_property_service
FOREIGN KEY (service_uuid)
REFERENCES icinga_service (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_service_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_command_property (
command_uuid bytea CHECK(LENGTH(command_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (command_uuid, property_uuid),
CONSTRAINT icinga_command_property_command
FOREIGN KEY (command_uuid)
REFERENCES icinga_command (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_command_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_notification_property (
notification_uuid bytea CHECK(LENGTH(notification_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (notification_uuid, property_uuid),
CONSTRAINT icinga_notification_property_notification
FOREIGN KEY (notification_uuid)
REFERENCES icinga_notification (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_notification_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_service_set_property (
service_set_uuid bytea CHECK(LENGTH(service_set_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (service_set_uuid, property_uuid),
CONSTRAINT icinga_service_set_property_service_set
FOREIGN KEY (service_set_uuid)
REFERENCES icinga_service_set (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_service_set_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_user_property (
user_uuid bytea CHECK(LENGTH(user_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (user_uuid, property_uuid),
CONSTRAINT icinga_user_property_user
FOREIGN KEY (user_uuid)
REFERENCES icinga_user (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_user_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE UNIQUE INDEX IF NOT EXISTS director_datalist_uuid_unique
ON director_datalist (uuid);
CREATE TABLE director_property_datalist (
list_uuid bytea CHECK(LENGTH(list_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
PRIMARY KEY (list_uuid, property_uuid),
CONSTRAINT director_list_property_list
FOREIGN KEY (list_uuid)
REFERENCES director_datalist (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT director_property_list_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
ALTER TABLE icinga_host_var
ADD COLUMN property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL;
ALTER TABLE icinga_service_var
ADD COLUMN property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL;
ALTER TABLE icinga_command_var
ADD COLUMN property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL;
ALTER TABLE icinga_notification_var
ADD COLUMN property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL;
ALTER TABLE icinga_service_set_var
ADD COLUMN property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL;
ALTER TABLE icinga_user_var
ADD COLUMN property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL;
INSERT INTO director_schema_migration
(schema_version, migration_time)
VALUES (192, NOW());

View file

@ -17,6 +17,18 @@ CREATE TYPE enum_merge_behaviour AS ENUM('set', 'add', 'substract', 'override');
CREATE TYPE enum_set_merge_behaviour AS ENUM('override', 'extend', 'blacklist');
CREATE TYPE enum_command_object_type AS ENUM('object', 'template', 'external_object');
CREATE TYPE enum_apply_object_type AS ENUM('object', 'template', 'apply', 'external_object');
CREATE TYPE enum_property_value_type AS ENUM(
'string',
'number',
'bool',
'fixed-array',
'dynamic-array',
'fixed-dictionary',
'dynamic-dictionary',
'datalist-strict',
'datalist-non-strict'
);
CREATE TYPE enum_state_name AS ENUM('OK', 'Warning', 'Critical', 'Unknown', 'Up', 'Down');
CREATE TYPE enum_type_name AS ENUM('DowntimeStart', 'DowntimeEnd', 'DowntimeRemoved', 'Custom', 'Acknowledgement', 'Problem', 'Recovery', 'FlappingStart', 'FlappingEnd');
CREATE TYPE enum_sync_rule_object_type AS ENUM(
@ -246,7 +258,7 @@ CREATE INDEX start_time_idx ON director_deployment_log (start_time);
CREATE TABLE director_datalist (
id serial,
uuid bytea CHECK(LENGTH(uuid) = 16) NOT NULL,
uuid bytea UNIQUE CHECK(LENGTH(uuid) = 16) NOT NULL,
list_name character varying(255) NOT NULL,
owner character varying(255) NOT NULL,
PRIMARY KEY (id)
@ -319,6 +331,47 @@ CREATE TABLE director_datafield_setting (
CREATE INDEX director_datafield_datafield ON director_datafield_setting (datafield_id);
CREATE TABLE director_property (
uuid bytea CHECK(LENGTH(uuid) = 16) NOT NULL,
parent_uuid bytea CHECK(LENGTH(parent_uuid) = 16) DEFAULT NULL,
key_name character varying(255) NOT NULL,
label character varying(255) DEFAULT NULL,
description text DEFAULT NULL,
value_type enum_property_value_type NOT NULL,
category_id integer DEFAULT NULL,
PRIMARY KEY (uuid),
CONSTRAINT director_property_category
FOREIGN KEY (category_id)
REFERENCES director_datafield_category (id)
ON DELETE RESTRICT
ON UPDATE CASCADE
);
CREATE UNIQUE INDEX unique_property_name_root
ON director_property (key_name)
WHERE parent_uuid IS NULL;
CREATE UNIQUE INDEX unique_property_name_parent
ON director_property (key_name, parent_uuid)
WHERE parent_uuid IS NOT NULL;
CREATE TABLE director_property_datalist (
list_uuid bytea CHECK(LENGTH(list_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
PRIMARY KEY (list_uuid, property_uuid),
CONSTRAINT director_list_property_list
FOREIGN KEY (list_uuid)
REFERENCES director_datalist (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT director_property_list_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE director_schema_migration (
schema_version SMALLINT NOT NULL,
migration_time TIMESTAMP WITH TIME ZONE NOT NULL,
@ -573,12 +626,31 @@ CREATE TABLE icinga_command_field (
);
CREATE TABLE icinga_command_property (
command_uuid bytea CHECK(LENGTH(command_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (command_uuid, property_uuid),
CONSTRAINT icinga_command_property_command
FOREIGN KEY (command_uuid)
REFERENCES icinga_command (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_command_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_command_var (
command_id integer NOT NULL,
checksum bytea DEFAULT NULL UNIQUE CHECK(LENGTH(checksum) = 20),
varname character varying(255) NOT NULL,
varvalue text DEFAULT NULL,
format enum_property_format NOT NULL DEFAULT 'string',
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL,
PRIMARY KEY (command_id, varname),
CONSTRAINT icinga_command_var_command
FOREIGN KEY (command_id)
@ -802,12 +874,30 @@ CREATE INDEX host_field_datafield ON icinga_host_field (datafield_id);
COMMENT ON COLUMN icinga_host_field.host_id IS 'Makes only sense for templates';
CREATE TABLE icinga_host_property (
host_uuid bytea CHECK(LENGTH(host_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (host_uuid, property_uuid),
CONSTRAINT icinga_host_property_host
FOREIGN KEY (host_uuid)
REFERENCES icinga_host (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_host_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_host_var (
host_id integer NOT NULL,
checksum bytea DEFAULT NULL UNIQUE CHECK(LENGTH(checksum) = 20),
varname character varying(255) NOT NULL,
varvalue text DEFAULT NULL,
format enum_property_format, -- immer string vorerst
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL,
PRIMARY KEY (host_id, varname),
CONSTRAINT icinga_host_var_host
FOREIGN KEY (host_id)
@ -975,12 +1065,31 @@ CREATE INDEX service_inheritance_service ON icinga_service_inheritance (service_
CREATE INDEX service_inheritance_service_parent ON icinga_service_inheritance (parent_service_id);
CREATE TABLE icinga_service_property (
service_uuid bytea CHECK(LENGTH(service_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (service_uuid, property_uuid),
CONSTRAINT icinga_service_property_service
FOREIGN KEY (service_uuid)
REFERENCES icinga_service (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_service_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_service_var (
service_id integer NOT NULL,
checksum bytea DEFAULT NULL UNIQUE CHECK(LENGTH(checksum) = 20),
varname character varying(255) NOT NULL,
varvalue text DEFAULT NULL,
format enum_property_format,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL,
PRIMARY KEY (service_id, varname),
CONSTRAINT icinga_service_var_service
FOREIGN KEY (service_id)
@ -1088,12 +1197,31 @@ CREATE INDEX service_set_inheritance_set ON icinga_service_set_inheritance (serv
CREATE INDEX service_set_inheritance_parent ON icinga_service_set_inheritance (parent_service_set_id);
CREATE TABLE icinga_service_set_property (
service_set_uuid bytea CHECK(LENGTH(service_set_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (service_set_uuid, property_uuid),
CONSTRAINT icinga_service_set_property_service_set
FOREIGN KEY (service_set_uuid)
REFERENCES icinga_service_set (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_service_set_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_service_set_var (
service_set_id integer NOT NULL,
checksum bytea DEFAULT NULL UNIQUE CHECK(LENGTH(checksum) = 20),
varname character varying(255) NOT NULL,
varvalue text DEFAULT NULL,
format enum_property_format NOT NULL DEFAULT 'string',
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL,
PRIMARY KEY (service_set_id, varname),
CONSTRAINT icinga_service_set_var_service_set
FOREIGN KEY (service_set_id)
@ -1370,6 +1498,7 @@ CREATE TABLE icinga_user_var (
varname character varying(255) NOT NULL,
varvalue text DEFAULT NULL,
format enum_property_format NOT NULL DEFAULT 'string',
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL,
PRIMARY KEY (user_id, varname),
CONSTRAINT icinga_user_var_user
FOREIGN KEY (user_id)
@ -1407,6 +1536,24 @@ CREATE INDEX user_field_datafield ON icinga_user_field (datafield_id);
COMMENT ON COLUMN icinga_user_field.user_id IS 'Makes only sense for templates';
CREATE TABLE icinga_user_property (
user_uuid bytea CHECK(LENGTH(user_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (user_uuid, property_uuid),
CONSTRAINT icinga_user_property_user
FOREIGN KEY (user_uuid)
REFERENCES icinga_user (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_user_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_usergroup (
id serial,
uuid bytea UNIQUE CHECK(LENGTH(uuid) = 16),
@ -1822,6 +1969,7 @@ CREATE TABLE icinga_notification_var (
varname VARCHAR(255) NOT NULL,
varvalue TEXT DEFAULT NULL,
format enum_property_format,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) DEFAULT NULL,
PRIMARY KEY (notification_id, varname),
CONSTRAINT icinga_notification_var_notification
FOREIGN KEY (notification_id)
@ -1858,6 +2006,24 @@ CREATE INDEX notification_field_datafield ON icinga_notification_field (datafiel
COMMENT ON COLUMN icinga_notification_field.notification_id IS 'Makes only sense for templates';
CREATE TABLE icinga_notification_property (
notification_uuid bytea CHECK(LENGTH(notification_uuid) = 16) NOT NULL,
property_uuid bytea CHECK(LENGTH(property_uuid) = 16) NOT NULL,
required enum_boolean NOT NULL DEFAULT 'n',
PRIMARY KEY (notification_uuid, property_uuid),
CONSTRAINT icinga_notification_property_notification
FOREIGN KEY (notification_uuid)
REFERENCES icinga_notification (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE,
CONSTRAINT icinga_notification_custom_property
FOREIGN KEY (property_uuid)
REFERENCES director_property (uuid)
ON DELETE CASCADE
ON UPDATE CASCADE
);
CREATE TABLE icinga_notification_inheritance (
notification_id integer NOT NULL,
parent_notification_id integer NOT NULL,
@ -2783,4 +2949,4 @@ CREATE INDEX branched_dependency_search_object_name ON branched_icinga_dependenc
INSERT INTO director_schema_migration
(schema_version, migration_time)
VALUES (190, NOW());
VALUES (192, NOW());