Merge branch 'feature/sync-keep-overrides-1307'
This commit is contained in:
commit
a10fa5abff
|
@ -43,6 +43,7 @@ before switching to a new version.
|
||||||
* FEATURE: new Property Modifier to url-encode values
|
* FEATURE: new Property Modifier to url-encode values
|
||||||
* FEATURE: new Property Modifier: uppercase the first character of each word
|
* FEATURE: new Property Modifier: uppercase the first character of each word
|
||||||
* FEATURE: Kickstart Helper now also imports Event Commands (#1389)
|
* FEATURE: Kickstart Helper now also imports Event Commands (#1389)
|
||||||
|
* FEATURE: Preserve _override_servicevars on sync, even when replacing vars (#1307)
|
||||||
|
|
||||||
### Internals
|
### Internals
|
||||||
* FEATURE: Html/Attribute now allows boolean properties
|
* FEATURE: Html/Attribute now allows boolean properties
|
||||||
|
|
|
@ -275,6 +275,32 @@ class CustomVariables implements Iterator, Countable, IcingaConfigRenderer
|
||||||
return $this;
|
return $this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function restoreStoredVar($key)
|
||||||
|
{
|
||||||
|
if (array_key_exists($key, $this->storedVars)) {
|
||||||
|
$this->vars[$key] = clone($this->storedVars[$key]);
|
||||||
|
$this->vars[$key]->setUnmodified();
|
||||||
|
$this->recheckForModifications();
|
||||||
|
$this->refreshIndex();
|
||||||
|
} elseif (array_key_exists($key, $this->vars)) {
|
||||||
|
unset($this->vars[$key]);
|
||||||
|
$this->recheckForModifications();
|
||||||
|
$this->refreshIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function recheckForModifications()
|
||||||
|
{
|
||||||
|
$this->modified = false;
|
||||||
|
foreach ($this->vars as $var) {
|
||||||
|
if ($var->hasBeenModified()) {
|
||||||
|
$this->modified = true;
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public function getOriginalVars()
|
public function getOriginalVars()
|
||||||
{
|
{
|
||||||
return $this->storedVars;
|
return $this->storedVars;
|
||||||
|
|
|
@ -79,6 +79,10 @@ class Sync
|
||||||
|
|
||||||
protected $replaceVars = false;
|
protected $replaceVars = false;
|
||||||
|
|
||||||
|
protected $hasPropertyDisabled = false;
|
||||||
|
|
||||||
|
protected $serviceOverrideKeyName;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var SyncRun
|
* @var SyncRun
|
||||||
*/
|
*/
|
||||||
|
@ -118,6 +122,7 @@ class Sync
|
||||||
* Retrieve modifications a given SyncRule would apply
|
* Retrieve modifications a given SyncRule would apply
|
||||||
*
|
*
|
||||||
* @return array Array of IcingaObject elements
|
* @return array Array of IcingaObject elements
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
public function getExpectedModifications()
|
public function getExpectedModifications()
|
||||||
{
|
{
|
||||||
|
@ -191,6 +196,10 @@ class Sync
|
||||||
$this->replaceVars = true;
|
$this->replaceVars = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($prop->destination_field === 'disabled') {
|
||||||
|
$this->hasPropertyDisabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (! strlen($prop->filter_expression)) {
|
if (! strlen($prop->filter_expression)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -263,6 +272,9 @@ class Sync
|
||||||
protected function fetchImportedData()
|
protected function fetchImportedData()
|
||||||
{
|
{
|
||||||
Benchmark::measure('Begin loading imported data');
|
Benchmark::measure('Begin loading imported data');
|
||||||
|
if ($this->rule->object_type === 'host') {
|
||||||
|
$this->serviceOverrideKeyName = $this->db->settings()->override_services_varname;
|
||||||
|
}
|
||||||
|
|
||||||
$this->imported = array();
|
$this->imported = array();
|
||||||
|
|
||||||
|
@ -575,9 +587,10 @@ class Sync
|
||||||
/**
|
/**
|
||||||
* Evaluates a SyncRule and returns a list of modified objects
|
* Evaluates a SyncRule and returns a list of modified objects
|
||||||
*
|
*
|
||||||
* TODO: This needs to be splitted into smaller methods
|
* TODO: Split this into smaller methods
|
||||||
*
|
*
|
||||||
* @return DbObject[] List of modified IcingaObjects
|
* @return DbObject|IcingaObject[] List of modified IcingaObjects
|
||||||
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
protected function prepare()
|
protected function prepare()
|
||||||
{
|
{
|
||||||
|
@ -586,8 +599,8 @@ class Sync
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->raiseLimits()
|
$this->raiseLimits()
|
||||||
->prepareCache()
|
|
||||||
->startMeasurements()
|
->startMeasurements()
|
||||||
|
->prepareCache()
|
||||||
->fetchSyncProperties()
|
->fetchSyncProperties()
|
||||||
->prepareRelatedImportSources()
|
->prepareRelatedImportSources()
|
||||||
->prepareSourceColumns()
|
->prepareSourceColumns()
|
||||||
|
@ -595,45 +608,16 @@ class Sync
|
||||||
->fetchImportedData()
|
->fetchImportedData()
|
||||||
->deferResolvers();
|
->deferResolvers();
|
||||||
|
|
||||||
// TODO: directly work on existing objects, remember imported keys, then purge
|
Benchmark::measure('Begin preparing updated objects');
|
||||||
$newObjects = $this->prepareNewObjects();
|
$newObjects = $this->prepareNewObjects();
|
||||||
|
|
||||||
$hasDisabled = false;
|
Benchmark::measure('Ready to process objects');
|
||||||
foreach ($this->syncProperties as $property) {
|
|
||||||
if ($property->get('destination_field') === 'disabled') {
|
|
||||||
$hasDisabled = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Benchmark::measure('Begin preparing updated objects');
|
|
||||||
|
|
||||||
/** @var DbObject|IcingaObject $object */
|
/** @var DbObject|IcingaObject $object */
|
||||||
foreach ($newObjects as $key => $object) {
|
foreach ($newObjects as $key => $object) {
|
||||||
if (array_key_exists($key, $this->objects)) {
|
$this->processObject($key, $object);
|
||||||
switch ($this->rule->get('update_policy')) {
|
|
||||||
case 'override':
|
|
||||||
$this->objects[$key]->replaceWith($object);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 'merge':
|
|
||||||
// TODO: re-evaluate merge settings. vars.x instead of
|
|
||||||
// just "vars" might suffice.
|
|
||||||
$this->objects[$key]->merge($object, $this->replaceVars);
|
|
||||||
if (! $hasDisabled && $object->hasProperty('disabled')) {
|
|
||||||
$this->objects[$key]->resetProperty('disabled');
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
// policy 'ignore', no action
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$this->objects[$key] = $object;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Benchmark::measure('Done preparing updated objects');
|
Benchmark::measure('Modified objects are ready, applying purge strategy');
|
||||||
|
|
||||||
$noAction = array();
|
$noAction = array();
|
||||||
foreach ($this->rule->purgeStrategy()->listObjectsToPurge() as $key) {
|
foreach ($this->rule->purgeStrategy()->listObjectsToPurge() as $key) {
|
||||||
if (array_key_exists($key, $newObjects)) {
|
if (array_key_exists($key, $newObjects)) {
|
||||||
|
@ -668,6 +652,68 @@ class Sync
|
||||||
return $this->objects;
|
return $this->objects;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $key
|
||||||
|
* @param DbObject|IcingaObject $object
|
||||||
|
* @throws IcingaException
|
||||||
|
* @throws \Icinga\Exception\ProgrammingError
|
||||||
|
*/
|
||||||
|
protected function processObject($key, $object)
|
||||||
|
{
|
||||||
|
if (array_key_exists($key, $this->objects)) {
|
||||||
|
$this->refreshObject($key, $object);
|
||||||
|
} else {
|
||||||
|
$this->addNewObject($key, $object);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $key
|
||||||
|
* @param DbObject|IcingaObject $object
|
||||||
|
* @throws IcingaException
|
||||||
|
* @throws \Icinga\Exception\ProgrammingError
|
||||||
|
*/
|
||||||
|
protected function refreshObject($key, $object)
|
||||||
|
{
|
||||||
|
$policy = $this->rule->get('update_policy');
|
||||||
|
|
||||||
|
switch ($policy) {
|
||||||
|
case 'override':
|
||||||
|
$this->objects[$key]->replaceWith($object);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'merge':
|
||||||
|
// TODO: re-evaluate merge settings. vars.x instead of
|
||||||
|
// just "vars" might suffice.
|
||||||
|
$this->objects[$key]->merge($object, $this->replaceVars);
|
||||||
|
if (! $this->hasPropertyDisabled && $object->hasProperty('disabled')) {
|
||||||
|
$this->objects[$key]->resetProperty('disabled');
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// policy 'ignore', no action
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($policy === 'override' || $policy === 'merge') {
|
||||||
|
if ($object instanceof IcingaHost) {
|
||||||
|
$keyName = $this->serviceOverrideKeyName;
|
||||||
|
if (! $object->hasInitializedVars() || ! isset($object->vars()->$key)) {
|
||||||
|
$this->objects[$key]->vars()->restoreStoredVar($keyName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $key
|
||||||
|
* @param DbObject|IcingaObject $object
|
||||||
|
*/
|
||||||
|
protected function addNewObject($key, $object)
|
||||||
|
{
|
||||||
|
$this->objects[$key] = $object;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Runs a SyncRule and applies all resulting changes
|
* Runs a SyncRule and applies all resulting changes
|
||||||
* @return int
|
* @return int
|
||||||
|
@ -692,6 +738,7 @@ class Sync
|
||||||
$created = 0;
|
$created = 0;
|
||||||
$modified = 0;
|
$modified = 0;
|
||||||
$deleted = 0;
|
$deleted = 0;
|
||||||
|
$failed = 0;
|
||||||
foreach ($objects as $object) {
|
foreach ($objects as $object) {
|
||||||
$this->setResolver($object);
|
$this->setResolver($object);
|
||||||
if ($object->shouldBeRemoved()) {
|
if ($object->shouldBeRemoved()) {
|
||||||
|
@ -701,12 +748,24 @@ class Sync
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($object->hasBeenModified()) {
|
if ($object->hasBeenModified()) {
|
||||||
if ($object->hasBeenLoadedFromDb()) {
|
$existing = $object->hasBeenLoadedFromDb();
|
||||||
|
|
||||||
|
try {
|
||||||
|
$object->store($db);
|
||||||
|
} catch (Exception $e) {
|
||||||
|
if ($this->singleObjectsAreAllowedToFail()) {
|
||||||
|
$failed++;
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
throw $e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($existing) {
|
||||||
$modified++;
|
$modified++;
|
||||||
} else {
|
} else {
|
||||||
$created++;
|
$created++;
|
||||||
}
|
}
|
||||||
$object->store($db);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1303,6 +1303,17 @@ abstract class IcingaObject extends DbObject implements IcingaConfigRenderer
|
||||||
return $this->vars;
|
return $this->vars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
* @throws ProgrammingError
|
||||||
|
*/
|
||||||
|
public function hasInitializedVars()
|
||||||
|
{
|
||||||
|
$this->assertCustomVarsSupport();
|
||||||
|
|
||||||
|
return $this->vars !== null;
|
||||||
|
}
|
||||||
|
|
||||||
public function getVarsTableName()
|
public function getVarsTableName()
|
||||||
{
|
{
|
||||||
return $this->getTableName() . '_var';
|
return $this->getTableName() . '_var';
|
||||||
|
|
Loading…
Reference in New Issue