chore: Refactor Mounts (#1236)

This commit is contained in:
MartinOscar 2025-05-09 19:18:20 +02:00 committed by GitHub
parent 8406f4686c
commit 7971dc13fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 142 additions and 47 deletions

View File

@ -3,7 +3,10 @@
namespace App\Filament\Admin\Resources;
use App\Filament\Admin\Resources\ServerResource\Pages;
use App\Models\Mount;
use App\Models\Server;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Get;
use Filament\Resources\Resource;
use Illuminate\Database\Eloquent\Builder;
@ -40,6 +43,29 @@ class ServerResource extends Resource
return (string) static::getEloquentQuery()->count() ?: null;
}
public static function getMountCheckboxList(Get $get): CheckboxList
{
$allowedMounts = Mount::all();
$node = $get('node_id');
$egg = $get('egg_id');
if ($node && $egg) {
$allowedMounts = $allowedMounts->filter(fn (Mount $mount) => ($mount->nodes->isEmpty() || $mount->nodes->contains($node)) &&
($mount->eggs->isEmpty() || $mount->eggs->contains($egg))
);
}
return CheckboxList::make('mounts')
->label('')
->relationship('mounts')
->live()
->options(fn () => $allowedMounts->mapWithKeys(fn ($mount) => [$mount->id => $mount->name]))
->descriptions(fn () => $allowedMounts->mapWithKeys(fn ($mount) => [$mount->id => "$mount->source -> $mount->target"]))
->helperText(fn () => $allowedMounts->isEmpty() ? trans('admin/server.no_mounts') : null)
->bulkToggleable()
->columnSpanFull();
}
public static function getPages(): array
{
return [

View File

@ -15,7 +15,6 @@ use Closure;
use Exception;
use Filament\Forms;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Component;
use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\Grid;
@ -744,7 +743,7 @@ class CreateServer extends CreateRecord
'lg' => 4,
])
->columnSpan(6)
->schema([
->schema(fn (Get $get) => [
Select::make('select_image')
->label(trans('admin/server.image_name'))
->live()
@ -798,14 +797,7 @@ class CreateServer extends CreateRecord
->valueLabel(trans('admin/server.description'))
->columnSpanFull(),
CheckboxList::make('mounts')
->label('Mounts')
->live()
->relationship('mounts')
->options(fn () => $this->node?->mounts->mapWithKeys(fn ($mount) => [$mount->id => $mount->name]) ?? [])
->descriptions(fn () => $this->node?->mounts->mapWithKeys(fn ($mount) => [$mount->id => "$mount->source -> $mount->target"]) ?? [])
->helperText(fn () => $this->node?->mounts->isNotEmpty() ? '' : 'No Mounts exist for this Node')
->columnSpanFull(),
ServerResource::getMountCheckboxList($get),
]),
]),
])

View File

@ -13,7 +13,6 @@ use App\Models\Allocation;
use App\Models\Database;
use App\Models\DatabaseHost;
use App\Models\Egg;
use App\Models\Mount;
use App\Models\Node;
use App\Models\Server;
use App\Models\ServerVariable;
@ -33,7 +32,6 @@ use Filament\Actions;
use Filament\Forms;
use Filament\Forms\Components\Actions as FormActions;
use Filament\Forms\Components\Actions\Action;
use Filament\Forms\Components\CheckboxList;
use Filament\Forms\Components\Component;
use Filament\Forms\Components\Fieldset;
use Filament\Forms\Components\Grid;
@ -651,14 +649,8 @@ class EditServer extends EditRecord
]),
Tab::make(trans('admin/server.mounts'))
->icon('tabler-layers-linked')
->schema([
CheckboxList::make('mounts')
->label('')
->relationship('mounts')
->options(fn (Server $server) => $server->node->mounts->filter(fn (Mount $mount) => $mount->eggs->contains($server->egg))->mapWithKeys(fn (Mount $mount) => [$mount->id => $mount->name]))
->descriptions(fn (Server $server) => $server->node->mounts->mapWithKeys(fn (Mount $mount) => [$mount->id => "$mount->source -> $mount->target"]))
->helperText(fn (Server $server) => $server->node->mounts->isNotEmpty() ? '' : trans('admin/server.no_mounts'))
->columnSpanFull(),
->schema(fn (Get $get) => [
ServerResource::getMountCheckboxList($get),
]),
Tab::make(trans('admin/server.databases'))
->hidden(fn () => !auth()->user()->can('viewList database'))

View File

@ -11,6 +11,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Support\Str;
/**
@ -283,6 +284,11 @@ class Egg extends Model implements Validatable
return $this->configFrom->file_denylist;
}
public function mounts(): MorphToMany
{
return $this->morphToMany(Mount::class, 'mountable');
}
/**
* Gets all servers associated with this egg.
*/

View File

@ -5,7 +5,7 @@ namespace App\Models;
use App\Contracts\Validatable;
use App\Traits\HasValidation;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
/**
* @property int $id
@ -102,24 +102,24 @@ class Mount extends Model implements Validatable
/**
* Returns all eggs that have this mount assigned.
*/
public function eggs(): BelongsToMany
public function eggs(): MorphToMany
{
return $this->belongsToMany(Egg::class);
return $this->morphedByMany(Egg::class, 'mountable');
}
/**
* Returns all nodes that have this mount assigned.
*/
public function nodes(): BelongsToMany
public function nodes(): MorphToMany
{
return $this->belongsToMany(Node::class);
return $this->morphedByMany(Node::class, 'mountable');
}
/**
* Returns all servers that have this mount assigned.
*/
public function servers(): BelongsToMany
public function servers(): MorphToMany
{
return $this->belongsToMany(Server::class);
return $this->morphedByMany(Server::class, 'mountable');
}
}

View File

@ -1,14 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class MountNode extends Model
{
protected $table = 'mount_node';
protected $primaryKey = null;
public $incrementing = false;
}

View File

@ -11,7 +11,7 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasManyThrough;
use Illuminate\Database\Eloquent\Relations\MorphToMany;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Str;
@ -241,9 +241,9 @@ class Node extends Model implements Validatable
return $this->maintenance_mode;
}
public function mounts(): HasManyThrough
public function mounts(): MorphToMany
{
return $this->hasManyThrough(Mount::class, MountNode::class, 'node_id', 'id', 'id', 'mount_id');
return $this->morphToMany(Mount::class, 'mountable');
}
/**

View File

@ -12,7 +12,6 @@ use Carbon\CarbonInterface;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
use Illuminate\Http\Client\ConnectionException;
use Illuminate\Notifications\Notifiable;
use Illuminate\Database\Query\JoinClause;
@ -350,9 +349,9 @@ class Server extends Model implements Validatable
return $this->hasMany(Backup::class);
}
public function mounts(): BelongsToMany
public function mounts(): MorphToMany
{
return $this->belongsToMany(Mount::class);
return $this->morphToMany(Mount::class, 'mountable');
}
/**

View File

@ -82,6 +82,7 @@ class AppServiceProvider extends ServiceProvider
'ssh_key' => Models\UserSSHKey::class,
'task' => Models\Task::class,
'user' => Models\User::class,
'node' => Models\Node::class,
]);
Http::macro(

View File

@ -0,0 +1,93 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::create('mountables', function (Blueprint $table) {
$table->unsignedInteger('mount_id');
$table->string('mountable_type');
$table->unsignedBigInteger('mountable_id');
$table->index(['mountable_id', 'mountable_type'], 'mountables_mountable_id_mountable_type_index');
$table->foreign('mount_id')
->references('id') // mount id
->on('mounts')
->onDelete('cascade');
$table->primary(['mount_id', 'mountable_id', 'mountable_type'],
'mountables_mountable_type_primary');
});
Schema::table('mount_node', function (Blueprint $table) {
$table->dropForeign(['node_id']);
$table->dropForeign(['mount_id']);
$table->dropUnique(['node_id', 'mount_id']);
});
$inserts = [];
$nodeMounts = DB::table('mount_node')->get();
$nodeMounts->each(function ($mount) use (&$inserts) {
$inserts[] = [
'mount_id' => $mount->mount_id,
'mountable_type' => 'node',
'mountable_id' => $mount->node_id,
];
});
Schema::table('mount_server', function (Blueprint $table) {
$table->dropForeign(['server_id']);
$table->dropForeign(['mount_id']);
$table->dropUnique(['server_id', 'mount_id']);
});
$serverMounts = DB::table('mount_server')->get();
$serverMounts->each(function ($mount) use (&$inserts) {
$inserts[] = [
'mount_id' => $mount->mount_id,
'mountable_type' => 'server',
'mountable_id' => $mount->server_id,
];
});
Schema::table('egg_mount', function (Blueprint $table) {
$table->dropForeign(['egg_id']);
$table->dropForeign(['mount_id']);
$table->dropUnique(['egg_id', 'mount_id']);
});
$eggMounts = DB::table('egg_mount')->get();
$eggMounts->each(function ($mount) use (&$inserts) {
$inserts[] = [
'mount_id' => $mount->mount_id,
'mountable_type' => 'egg',
'mountable_id' => $mount->egg_id,
];
});
DB::transaction(function () use ($inserts) {
DB::table('mountables')->insert($inserts);
});
Schema::drop('mount_node');
Schema::drop('mount_server');
Schema::drop('egg_mount');
}
/**
* Reverse the migrations.
*/
public function down(): void
{
// Not needed
}
};