mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-08 06:56:02 -04:00
feat(database): record which sqlite database a connected volume comes from
This commit is contained in:
@@ -80,13 +80,15 @@ class ConnectApplication extends Component
|
||||
throw new \Exception('Docker Compose applications are not supported: Coolify renames named volumes in compose files.');
|
||||
}
|
||||
|
||||
if ($application->persistentStorages()->where('name', $this->volumeName)->exists()) {
|
||||
if ($application->persistentStorages()->where('standalone_sqlite_id', $this->database->id)->exists()) {
|
||||
throw new \Exception("{$application->name} already mounts this database volume.");
|
||||
}
|
||||
|
||||
LocalPersistentVolume::create([
|
||||
'name' => $this->volumeName,
|
||||
'mount_path' => $this->mountPath,
|
||||
'host_path' => null,
|
||||
'standalone_sqlite_id' => $this->database->id,
|
||||
'resource_id' => $application->id,
|
||||
'resource_type' => $application->getMorphClass(),
|
||||
'is_preview_suffix_enabled' => false,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphMany;
|
||||
use Illuminate\Support\Str;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
@@ -22,6 +23,7 @@ class LocalPersistentVolume extends BaseModel
|
||||
'name',
|
||||
'mount_path',
|
||||
'host_path',
|
||||
'standalone_sqlite_id',
|
||||
'container_id',
|
||||
'resource_type',
|
||||
'resource_id',
|
||||
@@ -57,6 +59,14 @@ class LocalPersistentVolume extends BaseModel
|
||||
return $this->morphMany(ScheduledVolumeBackup::class, 'backupable');
|
||||
}
|
||||
|
||||
/**
|
||||
* The SQLite database this volume was connected from, if any.
|
||||
*/
|
||||
public function standaloneSqlite(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(StandaloneSqlite::class);
|
||||
}
|
||||
|
||||
public function abortIfScheduledBackupsExist(): void
|
||||
{
|
||||
if ($this->scheduledBackups()->exists()) {
|
||||
@@ -69,16 +79,17 @@ class LocalPersistentVolume extends BaseModel
|
||||
*/
|
||||
public function isSharedWithAnotherResource(): bool
|
||||
{
|
||||
if (filled($this->host_path)) {
|
||||
if ($this->standalone_sqlite_id !== null) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ($this->resource_type !== StandaloneSqlite::class) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return static::query()
|
||||
->where('standalone_sqlite_id', $this->resource_id)
|
||||
->where('name', $this->name)
|
||||
->where(function ($query): void {
|
||||
$query->where('resource_type', '!=', $this->resource_type)
|
||||
->orWhere('resource_id', '!=', $this->resource_id);
|
||||
})
|
||||
->exists();
|
||||
}
|
||||
|
||||
|
||||
@@ -306,6 +306,14 @@ class StandaloneSqlite extends BaseModel
|
||||
return $this->morphMany(LocalPersistentVolume::class, 'resource');
|
||||
}
|
||||
|
||||
/**
|
||||
* Volumes of other resources that mount this database's data volume.
|
||||
*/
|
||||
public function connectedVolumes()
|
||||
{
|
||||
return $this->hasMany(LocalPersistentVolume::class, 'standalone_sqlite_id');
|
||||
}
|
||||
|
||||
public function scheduledBackups()
|
||||
{
|
||||
return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
|
||||
|
||||
+26
@@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Records which SQLite database a volume was connected from, so the mount
|
||||
* can be traced back to its database without matching volume names.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('local_persistent_volumes', function (Blueprint $table) {
|
||||
$table->foreignId('standalone_sqlite_id')->nullable()->after('host_path')->constrained('standalone_sqlites')->nullOnDelete();
|
||||
});
|
||||
}
|
||||
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('local_persistent_volumes', function (Blueprint $table) {
|
||||
$table->dropConstrainedForeignId('standalone_sqlite_id');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -96,7 +96,9 @@ it('mounts the data volume into the selected application and redirects to its st
|
||||
|
||||
expect($volume->name)->toBe('sqlite-data-'.$this->sqlite->uuid)
|
||||
->and($volume->mount_path)->toBe('/app/database')
|
||||
->and($volume->is_preview_suffix_enabled)->toBeFalse();
|
||||
->and($volume->is_preview_suffix_enabled)->toBeFalse()
|
||||
->and($volume->standalone_sqlite_id)->toBe($this->sqlite->id)
|
||||
->and($this->sqlite->connectedVolumes()->sole()->resource->is($this->application))->toBeTrue();
|
||||
});
|
||||
|
||||
it('refuses to mount the volume into compose applications', function () {
|
||||
@@ -148,6 +150,7 @@ it('keeps a docker volume shared with another resource when the application volu
|
||||
'name' => 'sqlite-data-'.$this->sqlite->uuid,
|
||||
'mount_path' => StandaloneSqlite::DATA_DIRECTORY,
|
||||
'host_path' => null,
|
||||
'standalone_sqlite_id' => $this->sqlite->id,
|
||||
'resource_id' => $this->application->id,
|
||||
'resource_type' => $this->application->getMorphClass(),
|
||||
'is_preview_suffix_enabled' => false,
|
||||
|
||||
Reference in New Issue
Block a user