diff --git a/app/Actions/Database/StartClickhouse.php b/app/Actions/Database/StartClickhouse.php index 7fdfe9aeb..06cf8f719 100644 --- a/app/Actions/Database/StartClickhouse.php +++ b/app/Actions/Database/StartClickhouse.php @@ -51,7 +51,7 @@ class StartClickhouse ], 'labels' => defaultDatabaseLabels($this->database)->toArray(), 'healthcheck' => [ - 'test' => "clickhouse-client --password {$this->database->clickhouse_admin_password} --query 'SELECT 1'", + 'test' => "clickhouse-client --user {$this->database->clickhouse_admin_user} --password {$this->database->clickhouse_admin_password} --query 'SELECT 1'", 'interval' => '5s', 'timeout' => '5s', 'retries' => 10, @@ -152,12 +152,16 @@ class StartClickhouse $environment_variables->push("$env->key=$env->real_value"); } - if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_ADMIN_USER'))->isEmpty()) { - $environment_variables->push("CLICKHOUSE_ADMIN_USER={$this->database->clickhouse_admin_user}"); + if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_USER'))->isEmpty()) { + $environment_variables->push("CLICKHOUSE_USER={$this->database->clickhouse_admin_user}"); } - if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_ADMIN_PASSWORD'))->isEmpty()) { - $environment_variables->push("CLICKHOUSE_ADMIN_PASSWORD={$this->database->clickhouse_admin_password}"); + if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_PASSWORD'))->isEmpty()) { + $environment_variables->push("CLICKHOUSE_PASSWORD={$this->database->clickhouse_admin_password}"); + } + + if ($environment_variables->filter(fn ($env) => str($env)->contains('CLICKHOUSE_DB'))->isEmpty()) { + $environment_variables->push("CLICKHOUSE_DB={$this->database->clickhouse_db}"); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); diff --git a/app/Models/StandaloneClickhouse.php b/app/Models/StandaloneClickhouse.php index 6ac685618..ce5b967c2 100644 --- a/app/Models/StandaloneClickhouse.php +++ b/app/Models/StandaloneClickhouse.php @@ -25,7 +25,7 @@ class StandaloneClickhouse extends BaseModel static::created(function ($database) { LocalPersistentVolume::create([ 'name' => 'clickhouse-data-'.$database->uuid, - 'mount_path' => '/bitnami/clickhouse', + 'mount_path' => '/var/lib/clickhouse', 'host_path' => null, 'resource_id' => $database->id, 'resource_type' => $database->getMorphClass(), @@ -232,8 +232,8 @@ class StandaloneClickhouse extends BaseModel get: function () { $encodedUser = rawurlencode($this->clickhouse_admin_user); $encodedPass = rawurlencode($this->clickhouse_admin_password); - - return "clickhouse://{$encodedUser}:{$encodedPass}@{$this->uuid}:9000/{$this->clickhouse_db}"; + $database = $this->clickhouse_db ?? 'default'; + return "clickhouse://{$encodedUser}:{$encodedPass}@{$this->uuid}:9000/{$database}"; }, ); } @@ -249,8 +249,8 @@ class StandaloneClickhouse extends BaseModel } $encodedUser = rawurlencode($this->clickhouse_admin_user); $encodedPass = rawurlencode($this->clickhouse_admin_password); - - return "clickhouse://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/{$this->clickhouse_db}"; + $database = $this->clickhouse_db ?? 'default'; + return "clickhouse://{$encodedUser}:{$encodedPass}@{$serverIp}:{$this->public_port}/{$database}"; } return null; diff --git a/database/migrations/2024_04_10_091519_create_standalone_clickhouses_table.php b/database/migrations/2024_04_10_091519_create_standalone_clickhouses_table.php index 7433948b9..f7ea310cf 100644 --- a/database/migrations/2024_04_10_091519_create_standalone_clickhouses_table.php +++ b/database/migrations/2024_04_10_091519_create_standalone_clickhouses_table.php @@ -19,6 +19,7 @@ return new class extends Migration $table->string('clickhouse_admin_user')->default('default'); $table->text('clickhouse_admin_password'); + $table->string('clickhouse_db')->default('default'); $table->boolean('is_log_drain_enabled')->default(false); $table->boolean('is_include_timestamps')->default(false); @@ -26,7 +27,7 @@ return new class extends Migration $table->string('status')->default('exited'); - $table->string('image')->default('bitnami/clickhouse'); + $table->string('image')->default('clickhouse/clickhouse-server:latest'); $table->boolean('is_public')->default(false); $table->integer('public_port')->nullable(); diff --git a/database/migrations/2025_10_03_154100_update_clickhouse_image.php b/database/migrations/2025_10_03_154100_update_clickhouse_image.php deleted file mode 100644 index e57354037..000000000 --- a/database/migrations/2025_10_03_154100_update_clickhouse_image.php +++ /dev/null @@ -1,32 +0,0 @@ -string('image')->default('bitnamilegacy/clickhouse')->change(); - }); - // Optionally, update any existing rows with the old default to the new one - DB::table('standalone_clickhouses') - ->where('image', 'bitnami/clickhouse') - ->update(['image' => 'bitnamilegacy/clickhouse']); - } - - public function down() - { - Schema::table('standalone_clickhouses', function (Blueprint $table) { - $table->string('image')->default('bitnami/clickhouse')->change(); - }); - // Optionally, revert any changed values - DB::table('standalone_clickhouses') - ->where('image', 'bitnamilegacy/clickhouse') - ->update(['image' => 'bitnami/clickhouse']); - } -}; diff --git a/database/migrations/2025_11_28_000001_migrate_clickhouse_to_official_image.php b/database/migrations/2025_11_28_000001_migrate_clickhouse_to_official_image.php new file mode 100644 index 000000000..925b0dd09 --- /dev/null +++ b/database/migrations/2025_11_28_000001_migrate_clickhouse_to_official_image.php @@ -0,0 +1,52 @@ +string('clickhouse_db') + ->default('default') + ->after('clickhouse_admin_password'); + }); + } + StandaloneClickhouse::where(function ($query) { + $query->where('image', 'like', '%bitnami/clickhouse%') + ->orWhere('image', 'like', '%bitnamilegacy/clickhouse%'); + }) + ->update([ + 'image' => 'clickhouse/clickhouse-server:latest', + 'clickhouse_db' => DB::raw("COALESCE(clickhouse_db, 'default')") + ]); + + LocalPersistentVolume::where('resource_type', StandaloneClickhouse::class) + ->where('mount_path', '/bitnami/clickhouse') + ->update(['mount_path' => '/var/lib/clickhouse']); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + StandaloneClickhouse::where('image', 'clickhouse/clickhouse-server:latest') + ->update(['image' => 'bitnami/clickhouse']); + LocalPersistentVolume::where('resource_type', StandaloneClickhouse::class) + ->where('mount_path', '/var/lib/clickhouse') + ->update(['mount_path' => '/bitnami/clickhouse']); + } +}; diff --git a/tests/Unit/ClickhouseOfficialImageMigrationTest.php b/tests/Unit/ClickhouseOfficialImageMigrationTest.php new file mode 100644 index 000000000..9edf5d09c --- /dev/null +++ b/tests/Unit/ClickhouseOfficialImageMigrationTest.php @@ -0,0 +1,55 @@ +clickhouse_admin_user = 'testuser'; + $clickhouse->clickhouse_admin_password = 'testpass'; + $clickhouse->clickhouse_db = 'mydb'; + $clickhouse->uuid = 'test-uuid'; + + $internalUrl = $clickhouse->internal_db_url; + + expect($internalUrl) + ->toContain('mydb') + ->toContain('testuser') + ->toContain('test-uuid'); +}); + +test('clickhouse defaults to default database when clickhouse_db is null', function () { + $clickhouse = new StandaloneClickhouse(); + $clickhouse->clickhouse_admin_user = 'testuser'; + $clickhouse->clickhouse_admin_password = 'testpass'; + $clickhouse->clickhouse_db = null; + $clickhouse->uuid = 'test-uuid'; + + $internalUrl = $clickhouse->internal_db_url; + + expect($internalUrl)->toContain('/default'); +}); + +test('clickhouse external url uses correct database', function () { + $clickhouse = new StandaloneClickhouse(); + $clickhouse->clickhouse_admin_user = 'admin'; + $clickhouse->clickhouse_admin_password = 'secret'; + $clickhouse->clickhouse_db = 'production'; + $clickhouse->uuid = 'prod-uuid'; + $clickhouse->is_public = true; + $clickhouse->public_port = 8123; + + $clickhouse->destination = new class { + public $server; + public function __construct() { + $this->server = new class { + public function __get($name) { + if ($name === 'getIp') return '1.2.3.4'; + } + }; + } + }; + $externalUrl = $clickhouse->external_db_url; + + expect($externalUrl)->toContain('production'); + +});