Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Provide migration hook #188

Merged
merged 5 commits into from
Sep 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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