fix(database): always include MongoDB archive path in restores

This commit is contained in:
Andras Bacsai 2026-05-29 08:27:45 +02:00
parent 37a99e5f94
commit bbbd46ca26
2 changed files with 26 additions and 36 deletions

View file

@ -807,10 +807,7 @@ public function buildRestoreCommand(string $tmpPath): string
break; break;
case StandaloneMongodb::class: case StandaloneMongodb::class:
case 'mongodb': case 'mongodb':
$restoreCommand = $this->mongodbRestoreCommand; $restoreCommand = $this->mongodbRestoreCommand."{$tmpPath}";
if ($this->dumpAll === false) {
$restoreCommand .= "{$tmpPath}";
}
break; break;
default: default:
$restoreCommand = ''; $restoreCommand = '';

View file

@ -1,16 +1,26 @@
<?php <?php
use App\Livewire\Project\Database\Import; use App\Livewire\Project\Database\ImportForm;
function importFormWithResource(string $modelClass): ImportForm
{
$component = new class extends ImportForm
{
public $resource;
};
$database = Mockery::mock($modelClass);
$database->shouldReceive('getMorphClass')->andReturn($modelClass);
$component->resource = $database;
return $component;
}
test('buildRestoreCommand handles PostgreSQL without dumpAll', function () { test('buildRestoreCommand handles PostgreSQL without dumpAll', function () {
$component = new Import; $component = importFormWithResource('App\Models\StandalonePostgresql');
$component->dumpAll = false; $component->dumpAll = false;
$component->postgresqlRestoreCommand = 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB'; $component->postgresqlRestoreCommand = 'pg_restore -U $POSTGRES_USER -d $POSTGRES_DB';
$database = Mockery::mock('App\Models\StandalonePostgresql');
$database->shouldReceive('getMorphClass')->andReturn('App\Models\StandalonePostgresql');
$component->resource = $database;
$result = $component->buildRestoreCommand('/tmp/test.dump'); $result = $component->buildRestoreCommand('/tmp/test.dump');
expect($result)->toContain('pg_restore'); expect($result)->toContain('pg_restore');
@ -18,30 +28,21 @@
}); });
test('buildRestoreCommand handles PostgreSQL with dumpAll', function () { test('buildRestoreCommand handles PostgreSQL with dumpAll', function () {
$component = new Import; $component = importFormWithResource('App\Models\StandalonePostgresql');
$component->dumpAll = true; $component->dumpAll = true;
// This is the full dump-all command prefix that would be set in the updatedDumpAll method
$component->postgresqlRestoreCommand = 'psql -U $POSTGRES_USER -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname IS NOT NULL AND pid <> pg_backend_pid()" && psql -U $POSTGRES_USER -t -c "SELECT datname FROM pg_database WHERE NOT datistemplate" | xargs -I {} dropdb -U $POSTGRES_USER --if-exists {} && createdb -U $POSTGRES_USER postgres'; $component->postgresqlRestoreCommand = 'psql -U $POSTGRES_USER -c "SELECT pg_terminate_backend(pid) FROM pg_stat_activity WHERE datname IS NOT NULL AND pid <> pg_backend_pid()" && psql -U $POSTGRES_USER -t -c "SELECT datname FROM pg_database WHERE NOT datistemplate" | xargs -I {} dropdb -U $POSTGRES_USER --if-exists {} && createdb -U $POSTGRES_USER postgres';
$database = Mockery::mock('App\Models\StandalonePostgresql');
$database->shouldReceive('getMorphClass')->andReturn('App\Models\StandalonePostgresql');
$component->resource = $database;
$result = $component->buildRestoreCommand('/tmp/test.dump'); $result = $component->buildRestoreCommand('/tmp/test.dump');
expect($result)->toContain('gunzip -cf /tmp/test.dump'); expect($result)->toContain('gunzip -cf /tmp/test.dump');
expect($result)->toContain('psql -U $POSTGRES_USER postgres'); expect($result)->toContain('psql -U ${POSTGRES_USER} -d ${POSTGRES_DB:-${POSTGRES_USER:-postgres}}');
}); });
test('buildRestoreCommand handles MySQL without dumpAll', function () { test('buildRestoreCommand handles MySQL without dumpAll', function () {
$component = new Import; $component = importFormWithResource('App\Models\StandaloneMysql');
$component->dumpAll = false; $component->dumpAll = false;
$component->mysqlRestoreCommand = 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE'; $component->mysqlRestoreCommand = 'mysql -u $MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE';
$database = Mockery::mock('App\Models\StandaloneMysql');
$database->shouldReceive('getMorphClass')->andReturn('App\Models\StandaloneMysql');
$component->resource = $database;
$result = $component->buildRestoreCommand('/tmp/test.dump'); $result = $component->buildRestoreCommand('/tmp/test.dump');
expect($result)->toContain('mysql -u $MYSQL_USER'); expect($result)->toContain('mysql -u $MYSQL_USER');
@ -49,31 +50,23 @@
}); });
test('buildRestoreCommand handles MariaDB without dumpAll', function () { test('buildRestoreCommand handles MariaDB without dumpAll', function () {
$component = new Import; $component = importFormWithResource('App\Models\StandaloneMariadb');
$component->dumpAll = false; $component->dumpAll = false;
$component->mariadbRestoreCommand = 'mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE'; $component->mariadbRestoreCommand = 'mariadb -u $MARIADB_USER -p$MARIADB_PASSWORD $MARIADB_DATABASE';
$database = Mockery::mock('App\Models\StandaloneMariadb');
$database->shouldReceive('getMorphClass')->andReturn('App\Models\StandaloneMariadb');
$component->resource = $database;
$result = $component->buildRestoreCommand('/tmp/test.dump'); $result = $component->buildRestoreCommand('/tmp/test.dump');
expect($result)->toContain('mariadb -u $MARIADB_USER'); expect($result)->toContain('mariadb -u $MARIADB_USER');
expect($result)->toContain('< /tmp/test.dump'); expect($result)->toContain('< /tmp/test.dump');
}); });
test('buildRestoreCommand handles MongoDB', function () { test('buildRestoreCommand always appends the MongoDB archive path', function (bool $dumpAll) {
$component = new Import; $component = importFormWithResource('App\Models\StandaloneMongodb');
$component->dumpAll = false; $component->dumpAll = $dumpAll;
$component->mongodbRestoreCommand = 'mongorestore --authenticationDatabase=admin --username $MONGO_INITDB_ROOT_USERNAME --password $MONGO_INITDB_ROOT_PASSWORD --uri mongodb://localhost:27017 --gzip --archive='; $component->mongodbRestoreCommand = 'mongorestore --authenticationDatabase=admin --username $MONGO_INITDB_ROOT_USERNAME --password $MONGO_INITDB_ROOT_PASSWORD --uri mongodb://localhost:27017 --gzip --archive=';
$database = Mockery::mock('App\Models\StandaloneMongodb');
$database->shouldReceive('getMorphClass')->andReturn('App\Models\StandaloneMongodb');
$component->resource = $database;
$result = $component->buildRestoreCommand('/tmp/test.dump'); $result = $component->buildRestoreCommand('/tmp/test.dump');
expect($result)->toContain('mongorestore'); expect($result)->toContain('mongorestore');
expect($result)->toContain('/tmp/test.dump'); expect($result)->toContain('--archive=/tmp/test.dump');
}); })->with([false, true]);