Skip to content

Commit

Permalink
Provide migration hook (#188)
Browse files Browse the repository at this point in the history
  • Loading branch information
nilmerg authored Sep 19, 2023
2 parents ce3460f + b9d8ac3 commit a856edd
Show file tree
Hide file tree
Showing 11 changed files with 322 additions and 178 deletions.
19 changes: 19 additions & 0 deletions doc/80-Upgrading.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,25 @@
Upgrading Icinga Reporting is straightforward.
Usually the only manual steps involved are schema updates for the database.

## Upgrading to Version 1.0.0

Icinga Reporting version 1.0.0 requires a schema update for the database.
If you're already using Icinga Web version `>= 2.12`, then you don't need to perform any of these steps manually.
Icinga Web provides you the ability to perform such migrations in a simple way. You may be familiar with such an
automation if you're an Icinga Director user. For those who are not using the latest version of Icinga Web, please
follow the instructions below.

You may use the following command to apply the database schema upgrade file:
<!-- {% if not icingaDocs %} -->

**Note:** If you haven't installed this module from packages, then please adapt the schema path to the correct installation path.

<!-- {% endif %} -->

```
# mysql -u root -p reporting /usr/share/icingaweb2/modules/reporting/schema/mysql-upgrades/1.0.0.sql
```

## Upgrading to Version 0.10.0

Icinga Reporting version 0.10.0 requires a schema update for the database.
Expand Down
59 changes: 40 additions & 19 deletions library/Reporting/Database.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,33 +29,54 @@ protected function getDb(): RetryConnection
return new RetryConnection($config);
}

protected function listTimeframes()
/**
* List all reporting timeframes
*
* @return array<int, string>
*/
protected function listTimeframes(): array
{
$select = (new Sql\Select())
->from('timeframe')
->columns(['id', 'name']);

$timeframes = [];
/** @var stdClass $row */
foreach ($this->getDb()->select($select) as $row) {
$timeframes[$row->id] = $row->name;
}

return $timeframes;
return $this->list(
(new Sql\Select())
->from('timeframe')
->columns(['id', 'name'])
);
}

protected function listTemplates()
/**
* List all reporting templates
*
* @return array<int, string>
*/
protected function listTemplates(): array
{
$select = (new Sql\Select())
->from('template')
->columns(['id', 'name']);
return $this->list(
(new Sql\Select())
->from('template')
->columns(['id', 'name'])
);
}

$templates = [];
/**
* Helper method for list templates and timeframes
*
* @param Sql\Select $select
*
* @return array<int, string>
*/
private function list(Sql\Select $select): array
{
$result = [];
/** @var stdClass $row */
foreach ($this->getDb()->select($select) as $row) {
$templates[$row->id] = $row->name;
/** @var int $id */
$id = $row->id;
/** @var string $name */
$name = $row->name;

$result[$id] = $name;
}

return $templates;
return $result;
}
}
3 changes: 0 additions & 3 deletions library/Reporting/Model/Schedule.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ public function getColumns()
return [
'report_id',
'author',
'start',
'frequency',
'action',
'config',
'ctime',
Expand All @@ -38,7 +36,6 @@ public function getColumns()
public function createBehaviors(Behaviors $behaviors)
{
$behaviors->add(new MillisecondTimestamp([
'start',
'ctime',
'mtime'
]));
Expand Down
49 changes: 49 additions & 0 deletions library/Reporting/Model/Schema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

/* Icinga Reporting | (c) 2023 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Reporting\Model;

use DateTime;
use ipl\Orm\Behavior\BoolCast;
use ipl\Orm\Behavior\MillisecondTimestamp;
use ipl\Orm\Behaviors;
use ipl\Orm\Model;

/**
* A database model for reporting schema version table
*
* @property int $id Unique identifier of the database schema entries
* @property string $version The current schema version of Icinga Web
* @property DateTime $timestamp The insert/modify time of the schema entry
* @property bool $success Whether the database migration of the current version was successful
* @property ?string $reason The reason why the database migration has failed
*/
class Schema extends Model
{
public function getTableName(): string
{
return 'reporting_schema';
}

public function getKeyName()
{
return 'id';
}

public function getColumns(): array
{
return [
'version',
'timestamp',
'success',
'reason'
];
}

public function createBehaviors(Behaviors $behaviors): void
{
$behaviors->add(new BoolCast(['success']));
$behaviors->add(new MillisecondTimestamp(['timestamp']));
}
}
83 changes: 83 additions & 0 deletions library/Reporting/ProvidedHook/DbMigration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

/* Icinga Reporting | (c) 2023 Icinga GmbH | GPLv2 */

namespace Icinga\Module\Reporting\ProvidedHook;

use Icinga\Application\Hook\DbMigrationHook;
use Icinga\Module\Reporting\Database;
use Icinga\Module\Reporting\Model\Schema;
use ipl\Orm\Query;
use ipl\Sql\Connection;

class DbMigration extends DbMigrationHook
{
use Database {
getDb as private getReportingDb;
}

public function getName(): string
{
return $this->translate('Icinga Reporting');
}

public function providedDescriptions(): array
{
return [
'0.9.1' => $this->translate(
'Modifies all columns that uses current_timestamp to unix_timestamp and alters the database'
. ' engine of some tables.'
),
'0.10.0' => $this->translate('Creates the template table and adjusts some column types'),
'1.0.0' => $this->translate('Migrates all your configured report schedules to the new config.')
];
}

protected function getSchemaQuery(): Query
{
return Schema::on($this->getDb());
}

public function getDb(): Connection
{
return $this->getReportingDb();
}

public function getVersion(): string
{
if ($this->version === null) {
$conn = $this->getDb();
$schema = $this->getSchemaQuery()
->columns(['version', 'success'])
->orderBy('id', SORT_DESC)
->limit(2);

if (static::tableExists($conn, $schema->getModel()->getTableName())) {
/** @var Schema $version */
foreach ($schema as $version) {
if ($version->success) {
$this->version = $version->version;
}
}

if (! $this->version) {
// Schema version table exist, but the user has probably deleted the entry!
$this->version = '1.0.0';
}
} elseif (static::tableExists($conn, 'template')) {
// We have added Postgres support and the template table with 0.10.0.
// So, use this as the last (migrated) version.
$this->version = '0.10.0';
} elseif (static::getColumnType($conn, 'timeframe', 'name') === 'varchar(128)') {
// Upgrade script 0.9.1 alters the timeframe.name column from `varchar(255)` -> `varchar(128)`.
// Therefore, we can safely use this as the last migrated version.
$this->version = '0.9.1';
} else {
// Use the initial version as the last migrated schema version!
$this->version = '0.9.0';
}
}

return $this->version;
}
}
Loading

0 comments on commit a856edd

Please sign in to comment.