Merge remote-tracking branch 'origin/bugfix/sync-servicekeys' into mfrosch/head

This commit is contained in:
Markus Frosch 2018-09-20 15:59:04 +02:00
commit d4f9f297c2
2 changed files with 63 additions and 33 deletions

View File

@ -264,8 +264,8 @@ class Sync
$sourceId = $source->id;
// Provide an alias column for our key. TODO: double-check this!
$key = $source->key_column;
$this->sourceColumns[$sourceId][$key] = $key;
$keyColumn = $source->key_column;
$this->sourceColumns[$sourceId][$keyColumn] = $keyColumn;
$run = $source->fetchLastRun(true);
$usedColumns = SyncUtils::getRootVariables($this->sourceColumns[$sourceId]);
@ -296,36 +296,34 @@ class Sync
foreach ($rows as $row) {
if ($combinedKey) {
$key = SyncUtils::fillVariables($sourceKeyPattern, $row);
if (array_key_exists($key, $this->imported[$sourceId])) {
throw new IcingaException(
'Trying to import row "%s" (%s) twice: %s VS %s',
$key,
$sourceKeyPattern,
json_encode($this->imported[$sourceId][$key]),
json_encode($row)
);
}
} else {
if (! property_exists($row, $key)) {
if (! property_exists($row, $keyColumn)) {
throw new IcingaException(
'There is no key column "%s" in this row from "%s": %s',
$key,
$keyColumn,
$source->source_name,
json_encode($row)
);
}
$key = $row->$keyColumn;
}
if (! $this->rule->matches($row)) {
continue;
}
if ($combinedKey) {
$this->imported[$sourceId][$key] = $row;
} else {
$this->imported[$sourceId][$row->$key] = $row;
if (array_key_exists($key, $this->imported[$sourceId])) {
throw new IcingaException(
'Trying to import row "%s" (%s) twice: %s VS %s',
$key,
$sourceKeyPattern,
json_encode($this->imported[$sourceId][$key]),
json_encode($row)
);
}
$this->imported[$sourceId][$key] = $row;
}
unset($rows);
@ -381,14 +379,21 @@ class Sync
$this->objects = [];
$destinationKeyPattern = $this->rule->getDestinationKeyPattern();
$hasHostKey = strpos($destinationKeyPattern, '${host}') !== false;
$hasSetKey = strpos($destinationKeyPattern, '${service_set}') !== false;
$hasTypeName = strpos($destinationKeyPattern, '${object_type}') !== false;
foreach (IcingaObject::loadAllByType(
$this->rule->object_type,
$this->db
) as $object) {
if ($object instanceof IcingaService) {
if (strstr($destinationKeyPattern, '${host}') && $object->host_id === null) {
if ($hasHostKey && $object->host_id === null) {
continue;
} elseif (strstr($destinationKeyPattern, '${service_set}') && $object->service_set_id === null) {
} elseif ($hasSetKey && $object->service_set_id === null) {
continue;
} elseif ($hasTypeName && $object->object_type === 'object') {
// don't load objects in type mode (which are apply and templates)
continue;
}
}
@ -399,14 +404,22 @@ class Sync
);
if (array_key_exists($key, $this->objects)) {
throw new IcingaException(
'Combined destination key "%s" is not unique, got "%s" twice',
$destinationKeyPattern,
$key
);
if ($object->object_type === 'apply') {
// silently ignore all further apply with this name
// we have no unique key
// Note: this means non-unique apply objects are not reliably updated,
// but it *should* update the first in DB
continue;
} else {
throw new IcingaException(
'Combined destination key "%s" is not unique, got "%s" twice',
$destinationKeyPattern,
$key
);
}
} else {
$this->objects[$key] = $object;
}
$this->objects[$key] = $object;
}
} else {
$this->objects = IcingaObject::loadAllByType(

View File

@ -4,6 +4,7 @@ namespace Icinga\Module\Director\Objects;
use Icinga\Application\Benchmark;
use Icinga\Data\Filter\Filter;
use Icinga\Exception\MissingParameterException;
use Icinga\Module\Director\Data\Db\DbObject;
use Icinga\Module\Director\Db;
use Icinga\Module\Director\Exception\DuplicateKeyException;
@ -352,20 +353,23 @@ class SyncRule extends DbObject
$hasHost = false;
$hasObjectName = false;
$hasServiceSet = false;
$hasType = false;
foreach ($this->getSyncProperties() as $key => $property) {
if ($property->destination_field === 'host') {
$hasHost = $property->source_expression;
}
if ($property->destination_field === 'service_set') {
} elseif ($property->destination_field === 'service_set') {
$hasServiceSet = $property->source_expression;
}
if ($property->destination_field === 'object_name') {
} elseif ($property->destination_field === 'object_name') {
$hasObjectName = $property->source_expression;
} elseif ($property->destination_field === 'object_type') {
$hasType = $property->source_expression;
}
}
if ($hasHost !== false && $hasObjectName !== false) {
if ($hasObjectName === false) {
throw new MissingParameterException('You need to explicitly set object_name for services');
} elseif ($hasHost !== false) {
$this->hasCombinedKey = true;
$this->sourceKeyPattern = sprintf(
'%s!%s',
@ -374,7 +378,7 @@ class SyncRule extends DbObject
);
$this->destinationKeyPattern = '${host}!${object_name}';
} elseif ($hasServiceSet !== false && $hasObjectName !== false) {
} elseif ($hasServiceSet !== false) {
$this->hasCombinedKey = true;
$this->sourceKeyPattern = sprintf(
'%s!%s',
@ -383,6 +387,19 @@ class SyncRule extends DbObject
);
$this->destinationKeyPattern = '${service_set}!${object_name}';
} elseif ($hasType !== false) {
$this->hasCombinedKey = true;
$this->sourceKeyPattern = sprintf(
'%s!%s',
$hasType,
$hasObjectName
);
$this->destinationKeyPattern = '${object_type}!${object_name}';
} else {
throw new MissingParameterException(
'Can not sync services without object_name and one of: host, service_set, object_type'
);
}
} elseif ($this->get('object_type') === 'serviceSet') {
$hasHost = false;