mirror of
https://github.com/Icinga/icingaweb2-module-director.git
synced 2025-08-17 07:48:11 +02:00
Branch: remove outdated classes
This commit is contained in:
parent
5483093959
commit
f7d100ea24
@ -1,89 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Db\Branch;
|
||||
|
||||
use Icinga\Module\Director\Data\Json;
|
||||
use Icinga\Module\Director\Db;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
class BranchActivityStore
|
||||
{
|
||||
protected $connection;
|
||||
|
||||
protected $db;
|
||||
|
||||
protected $table = 'director_branch_activity';
|
||||
|
||||
public function __construct(Db $connection)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->db = $connection->getDbAdapter();
|
||||
}
|
||||
|
||||
public function count(UuidInterface $branchUuid)
|
||||
{
|
||||
$query = $this->db->select()
|
||||
->from($this->table, ['cnt' => 'COUNT(*)'])
|
||||
->where('branch_uuid = ?', $branchUuid->getBytes());
|
||||
|
||||
return (int) $this->db->fetchOne($query);
|
||||
}
|
||||
|
||||
public function loadAll(UuidInterface $branchUuid)
|
||||
{
|
||||
$query = $this->db->select()
|
||||
->from($this->table)
|
||||
->where('branch_uuid = ?', $branchUuid->getBytes())
|
||||
->order('change_time DESC');
|
||||
return $this->db->fetchAll($query);
|
||||
}
|
||||
|
||||
public static function objectModificationForDbRow($row)
|
||||
{
|
||||
$modification = ObjectModification::fromSerialization(json_decode($row->change_set));
|
||||
return $modification;
|
||||
}
|
||||
|
||||
/**
|
||||
* Must be run in a transaction!
|
||||
*
|
||||
* @param ObjectModification $modification
|
||||
* @param UuidInterface $branchUuid
|
||||
* @throws \Icinga\Module\Director\Exception\JsonEncodeException
|
||||
* @throws \Zend_Db_Adapter_Exception
|
||||
*/
|
||||
public function persistModification(ObjectModification $modification, UuidInterface $branchUuid)
|
||||
{
|
||||
$db = $this->db;
|
||||
$last = $db->fetchOne(
|
||||
$db->select()
|
||||
->from('director_branch_activity', 'checksum')
|
||||
->order('change_time DESC')
|
||||
->order('uuid') // Just in case, this gives a guaranteed order
|
||||
);
|
||||
// TODO: eventually implement more checks, allow only one change per millisecond
|
||||
// alternatively use last change_time plus one, when now < change_time
|
||||
if (strlen($last) !== 20) {
|
||||
$last = '';
|
||||
}
|
||||
$binaryUuid = Uuid::uuid4()->getBytes();
|
||||
$timestampMs = $this->now();
|
||||
$encoded = Json::encode($modification);
|
||||
|
||||
// HINT: checksums are useless! -> merge only
|
||||
$this->db->insert('director_branch_activity', [
|
||||
'uuid' => $binaryUuid,
|
||||
'branch_uuid' => $branchUuid->getBytes(),
|
||||
'change_set' => $encoded, // TODO: rename -> object_modification
|
||||
'change_time' => $timestampMs, // TODO: ns!!
|
||||
'checksum' => sha1("$last/$binaryUuid/$timestampMs/$encoded", true),
|
||||
'parent_checksum' => $last === '' ? null : $last,
|
||||
]);
|
||||
}
|
||||
|
||||
protected function now()
|
||||
{
|
||||
return floor(microtime(true) * 1000);
|
||||
}
|
||||
}
|
@ -1,267 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Db\Branch;
|
||||
|
||||
use Icinga\Module\Director\Data\Db\DbObjectTypeRegistry;
|
||||
use Icinga\Module\Director\Data\Json;
|
||||
use Icinga\Module\Director\Db;
|
||||
use Ramsey\Uuid\Uuid;
|
||||
use Ramsey\Uuid\UuidInterface;
|
||||
|
||||
class BranchModificationStore
|
||||
{
|
||||
// TODO: Ranges is weird. key = scheduled_downtime_id, range_type, range_key
|
||||
const ENCODED_ARRAYS = ['imports', 'groups', 'ranges'];
|
||||
|
||||
const ENCODED_DICTIONARIES = ['vars', 'arguments'];
|
||||
|
||||
protected $connection;
|
||||
|
||||
protected $db;
|
||||
|
||||
protected $shortType;
|
||||
|
||||
protected $table;
|
||||
|
||||
public function __construct(Db $connection, $shortType)
|
||||
{
|
||||
$this->connection = $connection;
|
||||
$this->shortType = $shortType;
|
||||
$this->table = "branched_icinga_$shortType";
|
||||
$this->db = $connection->getDbAdapter();
|
||||
}
|
||||
|
||||
public function loadAll(UuidInterface $branchUuid)
|
||||
{
|
||||
return $this->db->fetchAll($this->select()->where('branch_uuid = ?', $branchUuid->getBytes()));
|
||||
}
|
||||
|
||||
public function eventuallyLoadModification($objectId, UuidInterface $branchUuid)
|
||||
{
|
||||
if ($objectId) {
|
||||
$row = $this->fetchOptional($objectId, $branchUuid);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
if ($row) {
|
||||
$id = (int) $objectId;
|
||||
$class = DbObjectTypeRegistry::classByType($this->shortType);
|
||||
if ($row->deleted === 'y') {
|
||||
return ObjectModification::delete($class, $id, static::cleanupRow($row));
|
||||
}
|
||||
if ($row->created === 'y') {
|
||||
return ObjectModification::create($class, $row->object_name, static::cleanupRow($row));
|
||||
}
|
||||
|
||||
// TODO: Former properties null? DB Problem.
|
||||
return ObjectModification::modify($class, $id, null, static::filterNull(static::cleanupRow($row)));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function loadOptionalModificationByName($objectName, UuidInterface $branchUuid)
|
||||
{
|
||||
$row = $this->fetchOptionalByName($objectName, $branchUuid);
|
||||
if ($row) {
|
||||
$class = DbObjectTypeRegistry::classByType($this->shortType);
|
||||
if ($row->created === 'y') {
|
||||
return ObjectModification::create($class, $row->object_name, static::cleanupRow($row));
|
||||
}
|
||||
if ($row->deleted === 'y') {
|
||||
throw new \RuntimeException('Delete for a probably non-existing object? Not sure');
|
||||
// return ObjectModification::delete($class, $row->object_name, ...);
|
||||
}
|
||||
|
||||
// Hint: this is not correct. Former properties are missing. We finish up here, when loading renamed objects.
|
||||
return ObjectModification::modify($class, $row->object_name, [], static::filterNull(static::cleanupRow($row)));
|
||||
|
||||
// TODO: better exception, handle this in the frontend
|
||||
//throw new \RuntimeException('Got a modification for a probably non-existing object');
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function filterNull($row)
|
||||
{
|
||||
return (object) array_filter((array) $row, function ($value) {
|
||||
return $value !== null;
|
||||
});
|
||||
}
|
||||
|
||||
protected function cleanupRow($row)
|
||||
{
|
||||
unset($row->object_id, $row->class, $row->branch_uuid, $row->uuid, $row->created, $row->deleted);
|
||||
return $row;
|
||||
}
|
||||
|
||||
protected function fetchOptional($objectId, UuidInterface $branchUuid)
|
||||
{
|
||||
return $this->optionalRow($this->select()
|
||||
->where('object_id = ?', $objectId)
|
||||
->where('branch_uuid = ?', $branchUuid->getBytes()));
|
||||
}
|
||||
|
||||
protected function fetchOptionalByName($objectName, UuidInterface $branchUuid)
|
||||
{
|
||||
return $this->optionalRow($this->select()
|
||||
->where('object_name = ?', $objectName)
|
||||
->where('branch_uuid = ?', $branchUuid->getBytes()));
|
||||
}
|
||||
|
||||
protected function optionalRow($query)
|
||||
{
|
||||
if ($row = $this->db->fetchRow($query)) {
|
||||
$this->decodeEncodedProperties($row);
|
||||
return $row;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected function select()
|
||||
{
|
||||
return $this->db->select()->from($this->table);
|
||||
}
|
||||
|
||||
protected function decodeEncodedProperties($row)
|
||||
{
|
||||
foreach (array_merge(self::ENCODED_ARRAYS, self::ENCODED_DICTIONARIES) as $encodedProperty) {
|
||||
// vars, imports and groups might be null or not set at all (if not supported)
|
||||
if (! empty($row->$encodedProperty)) {
|
||||
$row->$encodedProperty = Json::decode($row->$encodedProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected function prepareModificationForStore(ObjectModification $modification)
|
||||
{
|
||||
// TODO.
|
||||
}
|
||||
|
||||
public function store(ObjectModification $modification, $objectId, UuidInterface $branchUuid)
|
||||
{
|
||||
if ($properties = $modification->getProperties()) {
|
||||
$properties = (array) $properties->jsonSerialize();
|
||||
} else {
|
||||
$properties = [];
|
||||
}
|
||||
|
||||
// Former properties are not needed, as they are dealt with in persistModification.
|
||||
if ($objectId) {
|
||||
$existing = $this->fetchOptional($objectId, $branchUuid);
|
||||
} else {
|
||||
$existing = null;
|
||||
}
|
||||
foreach (self::ENCODED_DICTIONARIES as $deepProperty) {
|
||||
if (isset($properties[$deepProperty])) {
|
||||
// TODO: flags
|
||||
$properties[$deepProperty] = Json::encode($properties[$deepProperty]);
|
||||
}
|
||||
}
|
||||
/* TODO: Nothing should be flat here, verify and remove this comment
|
||||
foreach (self::ENCODED_DICTIONARIES as $property) {
|
||||
$this->combineAndEncodeFlatDictionaries($properties, $existing, $property);
|
||||
}
|
||||
*/
|
||||
foreach (self::ENCODED_ARRAYS as $deepProperty) {
|
||||
if (isset($properties[$deepProperty])) {
|
||||
// TODO: flags
|
||||
$properties[$deepProperty] = Json::encode($properties[$deepProperty]);
|
||||
}
|
||||
}
|
||||
$this->connection->runFailSafeTransaction(function () use (
|
||||
$existing,
|
||||
$modification,
|
||||
$objectId,
|
||||
$branchUuid,
|
||||
$properties
|
||||
) {
|
||||
if ($existing) {
|
||||
if ($modification->isDeletion()) {
|
||||
$this->deleteExisting($existing->uuid);
|
||||
$this->delete($objectId, $branchUuid);
|
||||
} elseif ($existing->deleted === 'y') {
|
||||
$this->deleteExisting($existing->uuid);
|
||||
$this->create($objectId, $branchUuid, $properties);
|
||||
} else {
|
||||
$this->update($existing->uuid, $properties);
|
||||
}
|
||||
} else {
|
||||
if ($modification->isCreation()) {
|
||||
$this->create($objectId, $branchUuid, $properties);
|
||||
} elseif ($modification->isDeletion()) {
|
||||
$this->delete($objectId, $branchUuid);
|
||||
} else {
|
||||
$this->createModification($objectId, $branchUuid, $properties);
|
||||
}
|
||||
}
|
||||
$activities = new BranchActivityStore($this->connection);
|
||||
$activities->persistModification($modification, $branchUuid);
|
||||
});
|
||||
}
|
||||
|
||||
protected function combineAndEncodeFlatDictionaries(&$properties, $existing, $prefix)
|
||||
{
|
||||
if ($existing && ! empty($existing->$prefix)) {
|
||||
// $vars = (array) Json::decode($existing->vars);
|
||||
$vars = (array) ($existing->$prefix);
|
||||
} else {
|
||||
$vars = [];
|
||||
}
|
||||
$length = strlen($prefix) + 1;
|
||||
foreach ($properties as $key => $value) {
|
||||
if (substr($key, 0, $length) === "$prefix.") {
|
||||
$vars[substr($key, $length)] = $value;
|
||||
}
|
||||
}
|
||||
if (! empty($vars)) {
|
||||
foreach (array_keys($vars) as $key) {
|
||||
unset($properties["$prefix.$key"]);
|
||||
}
|
||||
$properties[$prefix] = Json::encode((object) $vars); // TODO: flags!
|
||||
}
|
||||
}
|
||||
|
||||
protected function deleteExisting($binaryUuid)
|
||||
{
|
||||
$this->db->delete($this->table, $this->db->quoteInto('uuid = ?', $binaryUuid));
|
||||
}
|
||||
|
||||
protected function create($objectId, UuidInterface $branchUuid, $properties)
|
||||
{
|
||||
$this->db->insert($this->table, [
|
||||
'branch_uuid' => $branchUuid->getBytes(),
|
||||
'uuid' => Uuid::uuid4()->getBytes(),
|
||||
'object_id' => $objectId,
|
||||
'created' => 'y',
|
||||
] + (array) $properties);
|
||||
}
|
||||
|
||||
protected function delete($objectId, UuidInterface $branchUuid)
|
||||
{
|
||||
$this->db->insert($this->table, [
|
||||
'branch_uuid' => $branchUuid->getBytes(),
|
||||
'uuid' => Uuid::uuid4()->getBytes(),
|
||||
'object_id' => $objectId,
|
||||
'deleted' => 'y',
|
||||
]);
|
||||
}
|
||||
|
||||
protected function createModification($objectId, UuidInterface $branchUuid, $properties)
|
||||
{
|
||||
$this->db->insert($this->table, [
|
||||
'branch_uuid' => $branchUuid->getBytes(),
|
||||
'uuid' => Uuid::uuid4()->getBytes(),
|
||||
'object_id' => $objectId,
|
||||
] + (array) $properties);
|
||||
}
|
||||
|
||||
protected function update($binaryUuid, $properties)
|
||||
{
|
||||
$this->db->update($this->table, [
|
||||
'uuid' => Uuid::uuid4()->getBytes(),
|
||||
] + (array) $properties, $this->db->quoteInto('uuid = ?', $binaryUuid));
|
||||
}
|
||||
}
|
@ -1,142 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Db\Branch;
|
||||
|
||||
use Icinga\Exception\ProgrammingError;
|
||||
use Icinga\Module\Director\Data\Db\DbObject;
|
||||
use Icinga\Module\Director\Db;
|
||||
use Icinga\Module\Director\Objects\IcingaObject;
|
||||
|
||||
class IcingaObjectModification
|
||||
{
|
||||
/**
|
||||
* @param DbObject $object
|
||||
* @return ObjectModification
|
||||
*/
|
||||
public static function getModification(DbObject $object)
|
||||
{
|
||||
if ($object->shouldBeRemoved()) {
|
||||
return static::delete($object);
|
||||
}
|
||||
|
||||
if ($object->hasBeenLoadedFromDb()) {
|
||||
return static::modify($object);
|
||||
}
|
||||
|
||||
return static::create($object);
|
||||
}
|
||||
|
||||
protected static function fixForeignKeys($object)
|
||||
{
|
||||
// TODO: Generic, _name?? Lookup?
|
||||
$keys = [
|
||||
'check_command_name',
|
||||
'check_period_name',
|
||||
'event_command_name',
|
||||
'command_endpoint_name',
|
||||
'zone_name',
|
||||
'host_name',
|
||||
];
|
||||
|
||||
foreach ($keys as $key) {
|
||||
if (property_exists($object, $key)) {
|
||||
$object->{substr($key, 0, -5)} = $object->$key;
|
||||
unset($object->$key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static function applyModification(ObjectModification $modification, DbObject $object = null, Db $db = null)
|
||||
{
|
||||
if ($modification->isDeletion()) {
|
||||
$object->markForRemoval();
|
||||
} elseif ($modification->isCreation()) {
|
||||
/** @var string|DbObject $class */
|
||||
$class = $modification->getClassName();
|
||||
$properties = $modification->getProperties()->jsonSerialize();
|
||||
self::fixForeignKeys($properties);
|
||||
$object = $class::create((array) $properties, $db);
|
||||
} else {
|
||||
// TODO: Add "reset Properties", those that have been nulled
|
||||
$properties = (array) $modification->getProperties()->jsonSerialize();
|
||||
foreach (BranchModificationStore::ENCODED_DICTIONARIES as $property) {
|
||||
self::flattenProperty($properties, $property);
|
||||
}
|
||||
if ($object === null) {
|
||||
echo '<pre>';
|
||||
debug_print_backtrace();
|
||||
echo '</pre>';
|
||||
exit;
|
||||
}
|
||||
foreach ($properties as $key => $value) {
|
||||
$object->set($key, $value);
|
||||
}
|
||||
}
|
||||
|
||||
// Just to be on the safe side
|
||||
if ($db) {
|
||||
$object->setConnection($db);
|
||||
}
|
||||
|
||||
return $object;
|
||||
}
|
||||
|
||||
public static function delete(DbObject $object)
|
||||
{
|
||||
return ObjectModification::delete(
|
||||
get_class($object),
|
||||
self::getKey($object),
|
||||
$object->toPlainObject(false, true)
|
||||
);
|
||||
}
|
||||
|
||||
public static function create(DbObject $object)
|
||||
{
|
||||
return ObjectModification::create(
|
||||
get_class($object),
|
||||
self::getKey($object),
|
||||
$object->toPlainObject(false, true)
|
||||
);
|
||||
}
|
||||
|
||||
protected static function getKey(DbObject $object)
|
||||
{
|
||||
return $object->getKeyParams();
|
||||
}
|
||||
|
||||
protected static function flattenProperty(array &$properties, $property)
|
||||
{
|
||||
// TODO: dots in varnames -> throw or escape?
|
||||
if (isset($properties[$property])) {
|
||||
foreach ((array) $properties[$property] as $key => $value) {
|
||||
$properties["$property.$key"] = $value;
|
||||
}
|
||||
unset($properties[$property]);
|
||||
}
|
||||
}
|
||||
|
||||
public static function modify(DbObject $object)
|
||||
{
|
||||
if (! $object instanceof IcingaObject) {
|
||||
throw new ProgrammingError('Plain object helpers for DbObject must be implemented');
|
||||
}
|
||||
$old = (array) $object->getPlainUnmodifiedObject();
|
||||
$new = (array) $object->toPlainObject(false, true);
|
||||
$unchangedKeys = [];
|
||||
foreach (BranchModificationStore::ENCODED_DICTIONARIES as $property) {
|
||||
self::flattenProperty($old, $property);
|
||||
self::flattenProperty($new, $property);
|
||||
}
|
||||
foreach ($old as $key => $value) {
|
||||
if (array_key_exists($key, $new) && $value === $new[$key]) {
|
||||
$unchangedKeys[] = $key;
|
||||
}
|
||||
}
|
||||
foreach ($unchangedKeys as $key) {
|
||||
unset($old[$key]);
|
||||
unset($new[$key]);
|
||||
}
|
||||
|
||||
return ObjectModification::modify(get_class($object), self::getKey($object), $old, $new);
|
||||
}
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Icinga\Module\Director\Db\Branch;
|
||||
|
||||
use Icinga\Module\Director\Data\DataArrayHelper;
|
||||
use Icinga\Module\Director\Data\Serializable;
|
||||
use Icinga\Module\Director\Data\SerializableValue;
|
||||
use InvalidArgumentException;
|
||||
|
||||
class ObjectModification implements Serializable
|
||||
{
|
||||
const ACTION_CREATE = 'create';
|
||||
const ACTION_MODIFY = 'modify';
|
||||
const ACTION_DELETE = 'delete';
|
||||
|
||||
protected static $serializationProperties = [
|
||||
'class',
|
||||
'key',
|
||||
'action',
|
||||
'properties',
|
||||
'formerProperties',
|
||||
];
|
||||
|
||||
/** @var string */
|
||||
protected $class;
|
||||
|
||||
/** @var \stdClass */
|
||||
protected $key;
|
||||
|
||||
/** @var string */
|
||||
protected $action;
|
||||
|
||||
/** @var SerializableValue|null */
|
||||
protected $properties;
|
||||
|
||||
/** @var SerializableValue|null */
|
||||
protected $formerProperties;
|
||||
|
||||
public function __construct(
|
||||
$class,
|
||||
$key,
|
||||
$action,
|
||||
SerializableValue $properties = null,
|
||||
SerializableValue $formerProperties = null
|
||||
) {
|
||||
$this->class = $class;
|
||||
$this->key = $key;
|
||||
$this->assertValidAction($action);
|
||||
$this->action = $action;
|
||||
$this->properties = $properties;
|
||||
$this->formerProperties = $formerProperties;
|
||||
}
|
||||
|
||||
public static function delete($class, $key, $formerProperties)
|
||||
{
|
||||
return new static(
|
||||
$class,
|
||||
$key,
|
||||
self::ACTION_DELETE,
|
||||
null,
|
||||
SerializableValue::wantSerializable($formerProperties)
|
||||
);
|
||||
}
|
||||
|
||||
public static function create($class, $key, $properties)
|
||||
{
|
||||
return new static($class, $key, self::ACTION_CREATE, SerializableValue::wantSerializable($properties));
|
||||
}
|
||||
|
||||
public static function modify($class, $key, $formerProperties, $properties)
|
||||
{
|
||||
return new static(
|
||||
$class,
|
||||
$key,
|
||||
self::ACTION_MODIFY,
|
||||
SerializableValue::wantSerializable($properties),
|
||||
SerializableValue::wantSerializable($formerProperties)
|
||||
);
|
||||
}
|
||||
|
||||
protected function assertValidAction($action)
|
||||
{
|
||||
if ($action !== self::ACTION_MODIFY
|
||||
&& $action !== self::ACTION_CREATE
|
||||
&& $action !== self::ACTION_DELETE
|
||||
) {
|
||||
throw new InvalidArgumentException("Valid action expected, got $action");
|
||||
}
|
||||
}
|
||||
|
||||
public function isDeletion()
|
||||
{
|
||||
return $this->action === self::ACTION_DELETE;
|
||||
}
|
||||
|
||||
public function isCreation()
|
||||
{
|
||||
return $this->action === self::ACTION_CREATE;
|
||||
}
|
||||
|
||||
public function isModification()
|
||||
{
|
||||
return $this->action === self::ACTION_MODIFY;
|
||||
}
|
||||
|
||||
public function getAction()
|
||||
{
|
||||
return $this->action;
|
||||
}
|
||||
|
||||
public function jsonSerialize()
|
||||
{
|
||||
return (object) [
|
||||
'class' => $this->class,
|
||||
'key' => $this->key,
|
||||
'action' => $this->action,
|
||||
'properties' => $this->properties,
|
||||
'formerProperties' => $this->formerProperties,
|
||||
];
|
||||
}
|
||||
|
||||
public function getProperties()
|
||||
{
|
||||
return $this->properties;
|
||||
}
|
||||
|
||||
public function getFormerProperties()
|
||||
{
|
||||
return $this->formerProperties;
|
||||
}
|
||||
|
||||
public function getClassName()
|
||||
{
|
||||
return $this->class;
|
||||
}
|
||||
|
||||
public function getKeyParams()
|
||||
{
|
||||
return $this->key;
|
||||
}
|
||||
|
||||
public static function fromSerialization($value)
|
||||
{
|
||||
$value = DataArrayHelper::wantArray($value);
|
||||
DataArrayHelper::failOnUnknownProperties($value, self::$serializationProperties);
|
||||
DataArrayHelper::requireProperties($value, ['class', 'key', 'action']);
|
||||
|
||||
return new static(
|
||||
$value['class'],
|
||||
$value['key'],
|
||||
$value['action'],
|
||||
isset($value['properties']) ? SerializableValue::fromSerialization($value['properties']) : null,
|
||||
isset($value['formerProperties']) ? SerializableValue::fromSerialization($value['formerProperties']) : null
|
||||
);
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user