Skip to content

Commit

Permalink
Provide migration hook & migrate jobs config to database
Browse files Browse the repository at this point in the history
  • Loading branch information
yhabteab committed Sep 15, 2023
1 parent 47afc99 commit 815cc3a
Show file tree
Hide file tree
Showing 7 changed files with 211 additions and 18 deletions.
39 changes: 39 additions & 0 deletions library/X509/Model/Schema.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

/* Icinga Web 2 X.509 Module | (c) 2023 Icinga GmbH | GPLv2 */

namespace Icinga\Module\X509\Model;

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

class Schema extends Model
{
public function getTableName(): string
{
return 'x509_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']));
}
}
98 changes: 98 additions & 0 deletions library/X509/ProvidedHook/DbMigration.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
<?php

/* Icinga Web 2 X.509 Module | (c) 2023 Icinga GmbH | GPLv2 */

namespace Icinga\Module\X509\ProvidedHook;

use Icinga\Application\Hook\DbMigrationHook;
use Icinga\Module\X509\Common\Database;
use Icinga\Module\X509\Model\Schema;
use ipl\Orm\Query;
use ipl\Sql;
use ipl\Sql\Adapter\Pgsql;

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

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

public function providedDescriptions(): array
{
return [
'1.0.0' => $this->translate(
'Adjusts the database type of several columns and changes some composed primary keys.'
),
'1.1.0' => $this->translate(
'Changes the composed x509_target index and x509_certificate valid from/to types to bigint.'
),
'1.2.0' => $this->translate(
'Changes all timestamp columns to bigint and adjusts enum types of "yes/no" to "n/y".'
),
'1.3.0' => $this->translate(
'Introduces the required tables to store jobs and job schedules in the database.'
)
];
}

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;

break;
}
}

if (! $this->version) {
// Schema version table exist, but the user has probably deleted the entry!
$this->version = '1.3.0';
}
} elseif (
$this->getDb()->getAdapter() instanceof Pgsql
|| static::getColumnType($conn, 'x509_certificate', 'ctime') === 'bigint(20) unsigned'
) {
// We modified a bunch of timestamp columns to bigint in x509 version 1.2.0.
// We have also added Postgres support with x509 version 1.2 and never had an upgrade scripts until now.
$this->version = '1.2.0';
} elseif (static::getColumnType($conn, 'x509_certificate_subject_alt_name', 'hash') !== null) {
// We know for sure that x509 version 1.0 has been applied, though not whether x509 version 1.1.0
// did too. Therefore, we have modified the 1.1.0 upgrade script to run multiple times without any
// errors so that we can use 1.0 as the last (migrated) version.
$this->version = '1.0.0';
} else {
// X509 version 1.0 was the first release of this module, but due to some reason it also contains
// an upgrade script and adds `hash` column. However, if this column doesn't exist yet, we need
// to use the lowest possible release value as the initial (last migrated) version.
$this->version = '0.0.0';
}
}

return $this->version;
}

public function getDb(): Sql\Connection
{
return $this->getX509Db();
}

protected function getSchemaQuery(): Query
{
return Schema::on($this->getDb());
}
}
4 changes: 4 additions & 0 deletions run.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,9 @@

// Icinga Web 2 X.509 Module | (c) 2018 Icinga GmbH | GPLv2

/** @var \Icinga\Application\Modules\Module $this */

$this->provideHook('DbMigration', '\\Icinga\\Module\\X509\\ProvidedHook\\DbMigration');

$this->provideHook('director/ImportSource', '\\Icinga\\Module\\X509\\ProvidedHook\\HostsImportSource');
$this->provideHook('director/ImportSource', '\\Icinga\\Module\\X509\\ProvidedHook\\ServicesImportSource');
30 changes: 21 additions & 9 deletions schema/mysql-upgrades/1.3.0.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS x509_job (
CREATE TABLE x509_job (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
name varchar(255) NOT NULL COLLATE utf8mb4_unicode_ci,
author varchar(255) NOT NULL COLLATE utf8mb4_unicode_ci,
Expand All @@ -12,7 +12,7 @@ CREATE TABLE IF NOT EXISTS x509_job (
UNIQUE (name)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE IF NOT EXISTS x509_schedule (
CREATE TABLE x509_schedule (
id int(10) unsigned NOT NULL AUTO_INCREMENT,
job_id int(10) unsigned NOT NULL,
name varchar(255) NOT NULL COLLATE utf8mb4_unicode_ci,
Expand All @@ -27,13 +27,25 @@ CREATE TABLE IF NOT EXISTS x509_schedule (

DELETE FROM x509_job_run;
ALTER TABLE x509_job_run
ADD COLUMN IF NOT EXISTS job_id int(10) unsigned NOT NULL AFTER id,
ADD COLUMN IF NOT EXISTS schedule_id int(10) unsigned DEFAULT NULL AFTER job_id,
DROP COLUMN IF EXISTS `name`,
DROP COLUMN IF EXISTS ctime,
DROP COLUMN IF EXISTS mtime,
DROP CONSTRAINT IF EXISTS fk_x509_job_run_job,
DROP CONSTRAINT IF EXISTS fk_x509_job_run_schedule;
ADD COLUMN job_id int(10) unsigned NOT NULL AFTER id,
ADD COLUMN schedule_id int(10) unsigned DEFAULT NULL AFTER job_id,
DROP COLUMN `name`,
DROP COLUMN ctime,
DROP COLUMN mtime;
ALTER TABLE x509_job_run
ADD CONSTRAINT fk_x509_job_run_job FOREIGN KEY (job_id) REFERENCES x509_job (id) ON DELETE CASCADE,
ADD CONSTRAINT fk_x509_job_run_schedule FOREIGN KEY (schedule_id) REFERENCES x509_schedule (id) ON DELETE CASCADE;

CREATE TABLE x509_schema (
id int unsigned NOT NULL AUTO_INCREMENT,
version varchar(64) NOT NULL,
timestamp bigint unsigned NOT NULL,
success enum ('n', 'y') DEFAULT NULL,
reason text DEFAULT NULL,

PRIMARY KEY (id),
CONSTRAINT idx_x509_schema_version UNIQUE (version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC;

INSERT INTO x509_schema (version, timestamp, success, reason)
VALUES ('1.3.0', UNIX_TIMESTAMP() * 1000, 'y', NULL);
14 changes: 14 additions & 0 deletions schema/mysql.schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -120,3 +120,17 @@ CREATE TABLE x509_job_run (
CONSTRAINT fk_x509_job_run_job FOREIGN KEY (job_id) REFERENCES x509_job (id) ON DELETE CASCADE,
CONSTRAINT fk_x509_job_run_schedule FOREIGN KEY (schedule_id) REFERENCES x509_schedule (id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

CREATE TABLE x509_schema (
id int unsigned NOT NULL AUTO_INCREMENT,
version varchar(64) NOT NULL,
timestamp bigint unsigned NOT NULL,
success enum ('n', 'y') DEFAULT NULL,
reason text DEFAULT NULL,

PRIMARY KEY (id),
CONSTRAINT idx_x509_schema_version UNIQUE (version)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin ROW_FORMAT=DYNAMIC;

INSERT INTO x509_schema (version, timestamp, success)
VALUES ('1.3.0', UNIX_TIMESTAMP() * 1000, 'y');
30 changes: 21 additions & 9 deletions schema/pgsql-upgrades/1.3.0.sql
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
CREATE TABLE IF NOT EXISTS x509_job (
CREATE TABLE x509_job (
id serial PRIMARY KEY,
name varchar(255) NOT NULL,
author varchar(255) NOT NULL,
Expand All @@ -11,7 +11,7 @@ CREATE TABLE IF NOT EXISTS x509_job (
UNIQUE (name)
);

CREATE TABLE IF NOT EXISTS x509_schedule (
CREATE TABLE x509_schedule (
id serial PRIMARY KEY,
job_id int NOT NULL,
name varchar(255) NOT NULL,
Expand All @@ -25,13 +25,25 @@ CREATE TABLE IF NOT EXISTS x509_schedule (

DELETE FROM x509_job_run;
ALTER TABLE x509_job_run
ADD COLUMN IF NOT EXISTS job_id int NOT NULL,
ADD COLUMN IF NOT EXISTS schedule_id int DEFAULT NULL,
DROP COLUMN IF EXISTS name,
DROP COLUMN IF EXISTS ctime,
DROP COLUMN IF EXISTS mtime,
DROP CONSTRAINT IF EXISTS fk_x509_job_run_job,
DROP CONSTRAINT IF EXISTS fk_x509_job_run_schedule;
ADD COLUMN job_id int NOT NULL,
ADD COLUMN schedule_id int DEFAULT NULL,
DROP COLUMN name,
DROP COLUMN ctime,
DROP COLUMN mtime;
ALTER TABLE x509_job_run
ADD CONSTRAINT fk_x509_job_run_job FOREIGN KEY (job_id) REFERENCES x509_job (id) ON DELETE CASCADE,
ADD CONSTRAINT fk_x509_job_run_schedule FOREIGN KEY (schedule_id) REFERENCES x509_schedule (id) ON DELETE CASCADE;

CREATE TABLE x509_schema (
id serial,
version varchar(64) NOT NULL,
timestamp bigint NOT NULL,
success boolenum DEFAULT NULL,
reason text DEFAULT NULL,

CONSTRAINT pk_x509_schema PRIMARY KEY (id),
CONSTRAINT idx_x509_schema_version UNIQUE (version)
);

INSERT INTO x509_schema (version, timestamp, success, reason)
VALUES ('1.3.0', UNIX_TIMESTAMP() * 1000, 'y', NULL);
14 changes: 14 additions & 0 deletions schema/pgsql.schema.sql
Original file line number Diff line number Diff line change
Expand Up @@ -146,3 +146,17 @@ CREATE TABLE x509_job_run (
CONSTRAINT fk_x509_job_run_job FOREIGN KEY (job_id) REFERENCES x509_job (id) ON DELETE CASCADE,
CONSTRAINT fk_x509_job_run_schedule FOREIGN KEY (schedule_id) REFERENCES x509_schedule (id) ON DELETE CASCADE
);

CREATE TABLE x509_schema (
id serial,
version varchar(64) NOT NULL,
timestamp bigint NOT NULL,
success boolenum DEFAULT NULL,
reason text DEFAULT NULL,

CONSTRAINT pk_x509_schema PRIMARY KEY (id),
CONSTRAINT idx_x509_schema_version UNIQUE (version)
);

INSERT INTO x509_schema (version, timestamp, success)
VALUES ('1.3.0', UNIX_TIMESTAMP() * 1000, 'y');

0 comments on commit 815cc3a

Please sign in to comment.