From dca738db8272cf57ad61ecbd9edc8bc953ea6fe5 Mon Sep 17 00:00:00 2001 From: Jeppe Bundgaard Date: Wed, 1 Jul 2026 10:28:40 +0200 Subject: [PATCH] Resolve edge schema DB config from env --- .../classes/edge_gateway_schema_bootstrap.php | 68 +++++++++++++++++++ .../EdgeGatewaySchemaBootstrapTest.php | 3 + 2 files changed, 71 insertions(+) diff --git a/services/nginx/app/modules/edgegateway/classes/edge_gateway_schema_bootstrap.php b/services/nginx/app/modules/edgegateway/classes/edge_gateway_schema_bootstrap.php index 50595a12..d3b5f70e 100644 --- a/services/nginx/app/modules/edgegateway/classes/edge_gateway_schema_bootstrap.php +++ b/services/nginx/app/modules/edgegateway/classes/edge_gateway_schema_bootstrap.php @@ -424,6 +424,11 @@ class edge_gateway_schema_bootstrap private static function pdo(): \PDO { + $envConfig = self::databaseConfigFromEnvironment(); + if ($envConfig !== null) { + return self::connectPdo($envConfig); + } + if (!class_exists(db::class, false)) { $dbClassPath = __DIR__ . '/../../../classes/db.php'; if (is_file($dbClassPath)) { @@ -437,4 +442,67 @@ class edge_gateway_schema_bootstrap return db::getPDO(); } + + /** + * @return array{host:string,user:string,password:string,database:string,port:int}|null + */ + private static function databaseConfigFromEnvironment(): ?array + { + $target = strtolower(self::envString('CONFIG_DB_TARGET') ?: 'live'); + if ($target !== 'debug') { + $target = 'live'; + } + + $host = self::databaseEnvValue('HOST', $target); + $user = self::databaseEnvValue('USER', $target); + $database = self::databaseEnvValue('DATABASE', $target); + if ($host === '' || $user === '' || $database === '') { + return null; + } + + return [ + 'host' => $host, + 'user' => $user, + 'password' => self::databaseEnvValue('PASSWORD', $target), + 'database' => $database, + 'port' => (int)(self::databaseEnvValue('PORT', $target) ?: 3306), + ]; + } + + private static function databaseEnvValue(string $key, string $target): string + { + $liveValue = self::envString('CONFIG_DB_' . $key); + $debugValue = self::envString('CONFIG_DB_DEBUG_' . $key); + + if ($target === 'debug' && $debugValue !== '') { + return $debugValue; + } + + return $liveValue; + } + + private static function envString(string $key): string + { + $value = getenv($key); + if ($value === false || $value === null) { + $value = $_ENV[$key] ?? $_SERVER[$key] ?? ''; + } + + return trim((string)$value); + } + + /** + * @param array{host:string,user:string,password:string,database:string,port:int} $config + */ + private static function connectPdo(array $config): \PDO + { + $port = $config['port'] > 0 ? $config['port'] : 3306; + $dsn = "mysql:host={$config['host']};port={$port};dbname={$config['database']};charset=utf8mb4"; + + return new \PDO($dsn, $config['user'], $config['password'], [ + \PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION, + \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, + \PDO::ATTR_EMULATE_PREPARES => false, + ]); + } } diff --git a/services/nginx/app/tests/Unit/Selfserve/EdgeGatewaySchemaBootstrapTest.php b/services/nginx/app/tests/Unit/Selfserve/EdgeGatewaySchemaBootstrapTest.php index 614384a8..ad447d72 100644 --- a/services/nginx/app/tests/Unit/Selfserve/EdgeGatewaySchemaBootstrapTest.php +++ b/services/nginx/app/tests/Unit/Selfserve/EdgeGatewaySchemaBootstrapTest.php @@ -42,6 +42,9 @@ it('stores operation metadata and event timelines for management workflows', fun expect($bootstrapContent)->toContain("ensureColumn('edge_gateway_operations', 'attempt_count', 'INT NOT NULL DEFAULT 0 AFTER last_progress_at')"); expect($bootstrapContent)->toContain('private static function syncOperationTypeColumns(): void'); expect($bootstrapContent)->toContain('SET type = operation_type'); + expect($bootstrapContent)->toContain('private static function databaseConfigFromEnvironment(): ?array'); + expect($bootstrapContent)->toContain("databaseEnvValue('HOST', \$target)"); + expect($bootstrapContent)->toContain('private static function connectPdo(array $config): \PDO'); expect($bootstrapContent)->toContain("ensureColumn('edge_gateway_operation_events', 'context_json', 'JSON NULL AFTER message')"); expect($bootstrapContent)->toContain("ensureColumn('edge_gateway_audit_logs', 'context_json', 'JSON NULL AFTER severity')"); expect($bootstrapContent)->toContain("ensureColumn('edge_gateway_log_entries', 'context_json', 'JSON NULL AFTER message')");