diff --git a/library/Reporting/Model/Schedule.php b/library/Reporting/Model/Schedule.php index 7f73aad8..6100d2a4 100644 --- a/library/Reporting/Model/Schedule.php +++ b/library/Reporting/Model/Schedule.php @@ -26,8 +26,6 @@ public function getColumns() return [ 'report_id', 'author', - 'start', - 'frequency', 'action', 'config', 'ctime', @@ -38,7 +36,6 @@ public function getColumns() public function createBehaviors(Behaviors $behaviors) { $behaviors->add(new MillisecondTimestamp([ - 'start', 'ctime', 'mtime' ])); diff --git a/library/Reporting/Model/Schema.php b/library/Reporting/Model/Schema.php new file mode 100644 index 00000000..8abe7b4e --- /dev/null +++ b/library/Reporting/Model/Schema.php @@ -0,0 +1,39 @@ +add(new BoolCast(['success'])); + $behaviors->add(new MillisecondTimestamp(['timestamp'])); + } +} diff --git a/library/Reporting/ProvidedHook/DbMigration.php b/library/Reporting/ProvidedHook/DbMigration.php new file mode 100644 index 00000000..9bd07552 --- /dev/null +++ b/library/Reporting/ProvidedHook/DbMigration.php @@ -0,0 +1,83 @@ +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; + } +} diff --git a/run.php b/run.php index ab6c4778..dc7b2922 100644 --- a/run.php +++ b/run.php @@ -8,6 +8,8 @@ /** @var \Icinga\Application\Modules\Module $this */ + $this->provideHook('DbMigration', '\\Icinga\\Module\\Reporting\\ProvidedHook\\DbMigration'); + $this->provideHook('reporting/Report', '\\Icinga\\Module\\Reporting\\Reports\\SystemReport'); $this->provideHook('reporting/Action', '\\Icinga\\Module\\Reporting\\Actions\\SendMail'); diff --git a/schema/mysql-upgrades/1.0.0.sql b/schema/mysql-upgrades/1.0.0.sql new file mode 100644 index 00000000..d790dba5 --- /dev/null +++ b/schema/mysql-upgrades/1.0.0.sql @@ -0,0 +1,17 @@ +ALTER TABLE schedule + DROP COLUMN start, + DROP COLUMN frequency; + +CREATE TABLE reporting_schema ( + id int unsigned NOT NULL AUTO_INCREMENT, + version varchar(64) NOT NULL, + timestamp bigint NOT NULL, + success enum ('n', 'y') DEFAULT NULL, + reason text DEFAULT NULL, + + PRIMARY KEY (id), + CONSTRAINT idx_reporting_schema_version UNIQUE (version) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; + +INSERT INTO reporting_schema (version, timestamp, success, reason) + VALUES ('1.0.0', UNIX_TIMESTAMP() * 1000, 'y', NULL); diff --git a/schema/mysql.schema.sql b/schema/mysql.schema.sql index 5f704817..f8b0fb70 100644 --- a/schema/mysql.schema.sql +++ b/schema/mysql.schema.sql @@ -74,8 +74,6 @@ CREATE TABLE schedule ( id int(10) unsigned NOT NULL AUTO_INCREMENT, report_id int(10) unsigned NOT NULL, author varchar(255) NOT NULL COLLATE utf8mb4_unicode_ci, - start bigint(20) unsigned NOT NULL, - frequency enum('minutely', 'hourly', 'daily', 'weekly', 'monthly'), action varchar(255) NOT NULL, config text NULL DEFAULT NULL, ctime bigint(20) unsigned NOT NULL, @@ -84,6 +82,20 @@ CREATE TABLE schedule ( CONSTRAINT schedule_report FOREIGN KEY (report_id) REFERENCES report (id) ON DELETE CASCADE ON UPDATE CASCADE ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin; +CREATE TABLE reporting_schema ( + id int unsigned NOT NULL AUTO_INCREMENT, + version varchar(64) NOT NULL, + timestamp bigint NOT NULL, + success enum ('n', 'y') DEFAULT NULL, + reason text DEFAULT NULL, + + PRIMARY KEY (id), + CONSTRAINT idx_reporting_schema_version UNIQUE (version) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC; + +INSERT INTO reporting_schema (version, timestamp, success) + VALUES ('1.0.0', UNIX_TIMESTAMP() * 1000, 'y'); + -- CREATE TABLE share ( -- id int(10) unsigned NOT NULL AUTO_INCREMENT, -- report_id int(10) unsigned NOT NULL, diff --git a/schema/pgsql-upgrades/1.0.0.sql b/schema/pgsql-upgrades/1.0.0.sql new file mode 100644 index 00000000..b0f6cfcf --- /dev/null +++ b/schema/pgsql-upgrades/1.0.0.sql @@ -0,0 +1,19 @@ +ALTER TABLE schedule + DROP COLUMN start, + DROP COLUMN frequency; + +CREATE TYPE boolenum AS ENUM ('n', 'y'); + +CREATE TABLE reporting_schema ( + id serial, + version varchar(64) NOT NULL, + timestamp bigint NOT NULL, + success boolenum DEFAULT NULL, + reason text DEFAULT NULL, + + CONSTRAINT pk_reporting_schema PRIMARY KEY (id), + CONSTRAINT idx_reporting_schema_version UNIQUE (version) +); + +INSERT INTO reporting_schema (version, timestamp, success, reason) + VALUES ('1.0.0', unix_timestamp() * 1000, 'y', NULL); diff --git a/schema/pgsql.schema.sql b/schema/pgsql.schema.sql index 329a65f8..d20289c0 100644 --- a/schema/pgsql.schema.sql +++ b/schema/pgsql.schema.sql @@ -1,9 +1,9 @@ +CREATE TYPE boolenum AS ENUM ('n', 'y'); + CREATE OR REPLACE FUNCTION unix_timestamp(timestamp with time zone DEFAULT NOW()) RETURNS bigint AS 'SELECT EXTRACT(EPOCH FROM $1)::bigint' LANGUAGE SQL; -CREATE TYPE frequency AS ENUM ('minutely', 'hourly', 'daily', 'weekly', 'monthly'); - CREATE TABLE template ( id serial PRIMARY KEY, author varchar(255) NOT NULL, @@ -73,11 +73,23 @@ CREATE TABLE schedule ( id serial PRIMARY KEY, report_id int NOT NULL, author varchar(255) NOT NULL, - start bigint NOT NULL, - frequency frequency, action varchar(255) NOT NULL, config text DEFAULT NULL, ctime bigint NOT NULL DEFAULT unix_timestamp() * 1000, mtime bigint NOT NULL DEFAULT unix_timestamp() * 1000, CONSTRAINT schedule_report FOREIGN KEY (report_id) REFERENCES report (id) ON DELETE CASCADE ON UPDATE CASCADE ); + +CREATE TABLE reporting_schema ( + id serial, + version varchar(64) NOT NULL, + timestamp bigint NOT NULL, + success boolenum DEFAULT NULL, + reason text DEFAULT NULL, + + CONSTRAINT pk_reporting_schema PRIMARY KEY (id), + CONSTRAINT idx_reporting_schema_version UNIQUE (version) +); + +INSERT INTO reporting_schema (version, timestamp, success) + VALUES ('1.0.0', UNIX_TIMESTAMP() * 1000, 'y');