Datalist: fix snapshot diff

fixes #2791
This commit is contained in:
Thomas Gelf 2023-08-25 17:15:08 +02:00
parent 5298243d94
commit fc7bfe7db9
4 changed files with 32 additions and 37 deletions

View File

@ -34,6 +34,10 @@ This version hasn't been released yet
* FIX: synchronizing Service (and -Set) Templates has been fixed (#2745, #2217) * FIX: synchronizing Service (and -Set) Templates has been fixed (#2745, #2217)
* FIX: null properties with Sync policy "ignore" are now being ignored (#2657) * FIX: null properties with Sync policy "ignore" are now being ignored (#2657)
# Configuration Baskets
* FEATURE: it's now possible to upload snapshots for existing baskets (#1952)
* FIX: basket now shows where to expect changes for lists from snapshots (#2791)
### REST API ### REST API
* FIX: Commands give 304 w/o ghost changes for same properties (#2660) * FIX: Commands give 304 w/o ghost changes for same properties (#2660)

View File

@ -304,16 +304,7 @@ class Exporter
protected function exportDatalistEntries(DirectorDatalist $list) protected function exportDatalistEntries(DirectorDatalist $list)
{ {
$entries = []; $entries = [];
$id = $list->get('id'); foreach ($list->getEntries() as $name => $entry) {
if ($id === null) {
return $entries;
}
$dbEntries = DirectorDatalistEntry::loadAllForList($list);
// Hint: they are loaded with entry_name key
ksort($dbEntries);
foreach ($dbEntries as $entry) {
if ($entry->shouldBeRemoved()) { if ($entry->shouldBeRemoved()) {
continue; continue;
} }

View File

@ -6,6 +6,7 @@ use gipfl\Json\JsonString;
use Icinga\Module\Director\Data\Exporter; use Icinga\Module\Director\Data\Exporter;
use Icinga\Module\Director\Data\ObjectImporter; use Icinga\Module\Director\Data\ObjectImporter;
use Icinga\Module\Director\Db; use Icinga\Module\Director\Db;
use Icinga\Module\Director\Objects\DirectorDatalist;
use Ramsey\Uuid\UuidInterface; use Ramsey\Uuid\UuidInterface;
use stdClass; use stdClass;

View File

@ -4,7 +4,7 @@ namespace Icinga\Module\Director\Objects;
use Exception; use Exception;
use Icinga\Module\Director\Data\Db\DbObject; 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\DirectorObject\Automation\ExportInterface;
use Icinga\Module\Director\Exception\DuplicateKeyException; use Icinga\Module\Director\Exception\DuplicateKeyException;
@ -23,16 +23,16 @@ class DirectorDatalist extends DbObject implements ExportInterface
]; ];
/** @var DirectorDatalistEntry[] */ /** @var DirectorDatalistEntry[] */
protected $storedEntries; protected $entries;
public function getUniqueIdentifier() public function getUniqueIdentifier()
{ {
return $this->get('list_name'); return $this->get('list_name');
} }
public function setEntries($entries) public function setEntries($entries): void
{ {
$existing = $this->getStoredEntries(); $existing = $this->getEntries();
$new = []; $new = [];
$seen = []; $seen = [];
@ -68,15 +68,13 @@ class DirectorDatalist extends DbObject implements ExportInterface
$this->hasBeenModified = true; $this->hasBeenModified = true;
} }
$this->storedEntries = $existing; $this->entries = $existing;
ksort($this->storedEntries); ksort($this->entries);
return $this;
} }
protected function beforeDelete() protected function beforeDelete()
{ {
if ($this->hasBeenUsed()) { if ($this->isInUse()) {
throw new Exception( throw new Exception(
sprintf( sprintf(
"Cannot delete '%s', as the datalist '%s' is currently being used.", "Cannot delete '%s', as the datalist '%s' is currently being used.",
@ -87,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(); $db = $this->getDb();
$dataFieldsCheck = $db->select() $dataFieldsCheck = $db->select()
@ -104,8 +106,8 @@ class DirectorDatalist extends DbObject implements ExportInterface
'l.id = dfs.setting_value', 'l.id = dfs.setting_value',
[] []
) )
->where('datatype = ?', $datalistType) ->where('datatype = ?', DataTypeDatalist::class)
->where('setting_value = ?', $this->get('id')); ->where('setting_value = ?', $id);
if ($db->fetchOne($dataFieldsCheck)) { if ($db->fetchOne($dataFieldsCheck)) {
return true; return true;
@ -114,7 +116,7 @@ class DirectorDatalist extends DbObject implements ExportInterface
$syncCheck = $db->select() $syncCheck = $db->select()
->from(['sp' =>'sync_property'], ['source_expression']) ->from(['sp' =>'sync_property'], ['source_expression'])
->where('sp.destination_field = ?', 'list_id') ->where('sp.destination_field = ?', 'list_id')
->where('sp.source_expression = ?', $this->get('id')); ->where('sp.source_expression = ?', $id);
if ($db->fetchOne($syncCheck)) { if ($db->fetchOne($syncCheck)) {
return true; return true;
@ -128,41 +130,38 @@ class DirectorDatalist extends DbObject implements ExportInterface
*/ */
public function onStore() public function onStore()
{ {
if ($this->storedEntries) { if ($this->entries) {
$db = $this->getConnection(); $db = $this->getConnection();
$removedKeys = []; $removedKeys = [];
$myId = $this->get('id'); $myId = $this->get('id');
foreach ($this->storedEntries as $key => $entry) { foreach ($this->entries as $key => $entry) {
if ($entry->shouldBeRemoved()) { if ($entry->shouldBeRemoved()) {
$entry->delete(); $entry->delete();
$removedKeys[] = $key; $removedKeys[] = $key;
} else { } else {
if (! $entry->hasBeenLoadedFromDb()) {
$entry->set('list_id', $myId);
}
$entry->set('list_id', $myId); $entry->set('list_id', $myId);
$entry->store($db); $entry->store($db);
} }
} }
foreach ($removedKeys as $key) { foreach ($removedKeys as $key) {
unset($this->storedEntries[$key]); unset($this->entries[$key]);
} }
} }
} }
protected function getStoredEntries() public function getEntries(): array
{ {
if ($this->storedEntries === null) { if ($this->entries === null) {
if ($id = $this->get('id')) { if ($this->get('id')) {
$this->storedEntries = DirectorDatalistEntry::loadAllForList($this); $this->entries = DirectorDatalistEntry::loadAllForList($this);
ksort($this->storedEntries); ksort($this->entries);
} else { } else {
$this->storedEntries = []; $this->entries = [];
} }
} }
return $this->storedEntries; return $this->entries;
} }
} }