diff --git a/app/Console/Commands/Egg/UpdateEggIndexCommand.php b/app/Console/Commands/Egg/UpdateEggIndexCommand.php new file mode 100644 index 000000000..8ef7646b2 --- /dev/null +++ b/app/Console/Commands/Egg/UpdateEggIndexCommand.php @@ -0,0 +1,46 @@ +error($exception->getMessage()); + + return 1; + } + + $index = []; + foreach ($data['nests'] as $nest) { + $nestName = $nest['nest_type']; + + $this->info("Nest: $nestName"); + + $nestEggs = []; + foreach ($nest['Eggs'] as $egg) { + $eggName = $egg['egg']['name']; + + $this->comment("Egg: $eggName"); + + $nestEggs[$egg['download_url']] = $eggName; + } + $index[$nestName] = $nestEggs; + + $this->info(''); + } + + cache()->forever('eggs.index', $index); + + return 0; + } +} diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 48fbe6b84..8421c1b82 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -3,6 +3,7 @@ namespace App\Console; use App\Console\Commands\Egg\CheckEggUpdatesCommand; +use App\Console\Commands\Egg\UpdateEggIndexCommand; use App\Console\Commands\Maintenance\CleanServiceBackupFilesCommand; use App\Console\Commands\Maintenance\PruneImagesCommand; use App\Console\Commands\Maintenance\PruneOrphanedBackupsCommand; @@ -41,7 +42,9 @@ class Kernel extends ConsoleKernel $schedule->command(CleanServiceBackupFilesCommand::class)->daily(); $schedule->command(PruneImagesCommand::class)->daily(); - $schedule->command(CheckEggUpdatesCommand::class)->hourly(); + + $schedule->command(CheckEggUpdatesCommand::class)->daily(); + $schedule->command(UpdateEggIndexCommand::class)->daily(); if (config('backups.prune_age')) { // Every 30 minutes, run the backup pruning command so that any abandoned backups can be deleted. diff --git a/app/Exceptions/Service/Deployment/NoViableNodeException.php b/app/Exceptions/Service/Deployment/NoViableNodeException.php new file mode 100644 index 000000000..432c42703 --- /dev/null +++ b/app/Exceptions/Service/Deployment/NoViableNodeException.php @@ -0,0 +1,7 @@ +label(trans('admin/server.docker_image')), SelectColumn::make('allocation.id') ->label(trans('admin/server.primary_allocation')) - ->options(fn (Server $server) => [$server->allocation->id => $server->allocation->address]) - ->selectablePlaceholder(false) + ->disabled() + ->options(fn (Server $server) => $server->allocations->take(1)->mapWithKeys(fn ($allocation) => [$allocation->id => $allocation->address])) + ->placeholder('None') ->sortable(), ]); } diff --git a/app/Filament/Admin/Resources/NodeResource/RelationManagers/AllocationsRelationManager.php b/app/Filament/Admin/Resources/NodeResource/RelationManagers/AllocationsRelationManager.php index 84cc9f032..547b010c1 100644 --- a/app/Filament/Admin/Resources/NodeResource/RelationManagers/AllocationsRelationManager.php +++ b/app/Filament/Admin/Resources/NodeResource/RelationManagers/AllocationsRelationManager.php @@ -62,6 +62,9 @@ class AllocationsRelationManager extends RelationManager TextInputColumn::make('ip_alias') ->searchable() ->label(trans('admin/node.table.alias')), + TextInputColumn::make('notes') + ->label(trans('admin/node.table.allocation_notes')) + ->placeholder(trans('admin/node.table.no_notes')), SelectColumn::make('ip') ->options(fn (Allocation $allocation) => collect($this->getOwnerRecord()->ipAddresses())->merge([$allocation->ip])->mapWithKeys(fn (string $ip) => [$ip => $ip])) ->selectablePlaceholder(false) @@ -85,8 +88,7 @@ class AllocationsRelationManager extends RelationManager ->label(trans('admin/node.table.alias')) ->inlineLabel() ->default(null) - ->helperText(trans('admin/node.alias_help')) - ->required(false), + ->helperText(trans('admin/node.alias_help')), TagsInput::make('allocation_ports') ->placeholder('27015, 27017-27019') ->label(trans('admin/node.ports')) diff --git a/app/Filament/Admin/Resources/NodeResource/RelationManagers/NodesRelationManager.php b/app/Filament/Admin/Resources/NodeResource/RelationManagers/NodesRelationManager.php index 75bf98626..1ae50e2a4 100644 --- a/app/Filament/Admin/Resources/NodeResource/RelationManagers/NodesRelationManager.php +++ b/app/Filament/Admin/Resources/NodeResource/RelationManagers/NodesRelationManager.php @@ -43,8 +43,10 @@ class NodesRelationManager extends RelationManager ->sortable(), SelectColumn::make('allocation.id') ->label(trans('admin/node.primary_allocation')) - ->options(fn (Server $server) => [$server->allocation->id => $server->allocation->address]) - ->selectablePlaceholder(false) + ->disabled(fn (Server $server) => $server->allocations->count() <= 1) + ->options(fn (Server $server) => $server->allocations->take(1)->mapWithKeys(fn ($allocation) => [$allocation->id => $allocation->address])) + ->selectablePlaceholder(fn (SelectColumn $select) => !$select->isDisabled()) + ->placeholder('None') ->sortable(), TextColumn::make('memory')->label(trans('admin/node.memory'))->icon('tabler-device-desktop-analytics'), TextColumn::make('cpu')->label(trans('admin/node.cpu'))->icon('tabler-cpu'), diff --git a/app/Filament/Admin/Resources/ServerResource/Pages/CreateServer.php b/app/Filament/Admin/Resources/ServerResource/Pages/CreateServer.php index 284de2bc8..e63a7dd9f 100644 --- a/app/Filament/Admin/Resources/ServerResource/Pages/CreateServer.php +++ b/app/Filament/Admin/Resources/ServerResource/Pages/CreateServer.php @@ -132,12 +132,12 @@ class CreateServer extends CreateRecord ->live() ->relationship('node', 'name', fn (Builder $query) => $query->whereIn('id', auth()->user()->accessibleNodes()->pluck('id'))) ->searchable() + ->required() ->preload() ->afterStateUpdated(function (Set $set, $state) { $set('allocation_id', null); $this->node = Node::find($state); - }) - ->required(), + }), Select::make('owner_id') ->preload() @@ -198,7 +198,7 @@ class CreateServer extends CreateRecord $set('allocation_additional', null); $set('allocation_additional.needstobeastringhere.extra_allocations', null); }) - ->getOptionLabelFromRecordUsing(fn (Allocation $allocation) => $allocation->address) + ->getOptionLabelFromRecordUsing(fn (Allocation $allocation) => $allocation->address ?? '') ->placeholder(function (Get $get) { $node = Node::find($get('node_id')); @@ -252,9 +252,7 @@ class CreateServer extends CreateRecord return collect( $assignmentService->handle(Node::find($get('node_id')), $data) )->first(); - }) - ->required(), - + }), Repeater::make('allocation_additional') ->label(trans('admin/server.additional_allocations')) ->columnSpan([ @@ -274,7 +272,7 @@ class CreateServer extends CreateRecord ->prefixIcon('tabler-network') ->label('Additional Allocations') ->columnSpan(2) - ->disabled(fn (Get $get) => $get('../../node_id') === null) + ->disabled(fn (Get $get) => $get('../../allocation_id') === null || $get('../../node_id') === null) ->searchable(['ip', 'port', 'ip_alias']) ->getOptionLabelFromRecordUsing(fn (Allocation $allocation) => $allocation->address) ->placeholder(trans('admin/server.select_additional')) @@ -837,7 +835,9 @@ class CreateServer extends CreateRecord protected function handleRecordCreation(array $data): Model { - $data['allocation_additional'] = collect($data['allocation_additional'])->filter()->all(); + if ($allocation_additional = array_get($data, 'allocation_additional')) { + $data['allocation_additional'] = collect($allocation_additional)->filter()->all(); + } try { return $this->serverCreationService->handle($data); diff --git a/app/Filament/Admin/Resources/ServerResource/Pages/EditServer.php b/app/Filament/Admin/Resources/ServerResource/Pages/EditServer.php index 8b387bd94..a76002d77 100644 --- a/app/Filament/Admin/Resources/ServerResource/Pages/EditServer.php +++ b/app/Filament/Admin/Resources/ServerResource/Pages/EditServer.php @@ -1032,17 +1032,20 @@ class EditServer extends EditRecord ->options(fn (Server $server) => Node::whereNot('id', $server->node->id)->pluck('name', 'id')->all()), Select::make('allocation_id') ->label(trans('admin/server.primary_allocation')) - ->required() + ->disabled(fn (Get $get, Server $server) => !$get('node_id') || !$server->allocation_id) + ->required(fn (Server $server) => $server->allocation_id) ->prefixIcon('tabler-network') - ->disabled(fn (Get $get) => !$get('node_id')) ->options(fn (Get $get) => Allocation::where('node_id', $get('node_id'))->whereNull('server_id')->get()->mapWithKeys(fn (Allocation $allocation) => [$allocation->id => $allocation->address])) ->searchable(['ip', 'port', 'ip_alias']) ->placeholder(trans('admin/server.select_allocation')), Select::make('allocation_additional') ->label(trans('admin/server.additional_allocations')) + ->disabled(fn (Get $get, Server $server) => !$get('node_id') || $server->allocations->count() <= 1) ->multiple() + ->minItems(fn (Select $select) => $select->getMaxItems()) + ->maxItems(fn (Select $select, Server $server) => $select->isDisabled() ? null : $server->allocations->count() - 1) ->prefixIcon('tabler-network') - ->disabled(fn (Get $get) => !$get('node_id')) + ->required(fn (Server $server) => $server->allocations->count() > 1) ->options(fn (Get $get) => Allocation::where('node_id', $get('node_id'))->whereNull('server_id')->when($get('allocation_id'), fn ($query) => $query->whereNot('id', $get('allocation_id')))->get()->mapWithKeys(fn (Allocation $allocation) => [$allocation->id => $allocation->address])) ->searchable(['ip', 'port', 'ip_alias']) ->placeholder(trans('admin/server.select_additional')), diff --git a/app/Filament/Admin/Resources/ServerResource/Pages/ListServers.php b/app/Filament/Admin/Resources/ServerResource/Pages/ListServers.php index 85f6ea2dc..0ae0ab03c 100644 --- a/app/Filament/Admin/Resources/ServerResource/Pages/ListServers.php +++ b/app/Filament/Admin/Resources/ServerResource/Pages/ListServers.php @@ -73,14 +73,17 @@ class ListServers extends ListRecords ->searchable(), SelectColumn::make('allocation_id') ->label(trans('admin/server.primary_allocation')) - ->hidden(!auth()->user()->can('update server')) // TODO: update to policy check (fn (Server $server) --> $server is empty) + ->hidden(fn () => !auth()->user()->can('update server')) // TODO: update to policy check (fn (Server $server) --> $server is empty) + ->disabled(fn (Server $server) => $server->allocations->count() <= 1) ->options(fn (Server $server) => $server->allocations->mapWithKeys(fn ($allocation) => [$allocation->id => $allocation->address])) - ->selectablePlaceholder(false) + ->selectablePlaceholder(fn (Server $server) => $server->allocations->count() <= 1) + ->placeholder('None') ->sortable(), TextColumn::make('allocation_id_readonly') ->label(trans('admin/server.primary_allocation')) - ->hidden(auth()->user()->can('update server')) // TODO: update to policy check (fn (Server $server) --> $server is empty) - ->state(fn (Server $server) => $server->allocation->address), + ->hidden(fn () => auth()->user()->can('update server')) // TODO: update to policy check (fn (Server $server) --> $server is empty) + ->disabled(fn (Server $server) => $server->allocations->count() <= 1) + ->state(fn (Server $server) => $server->allocation->address ?? 'None'), TextColumn::make('image')->hidden(), TextColumn::make('backups_count') ->counts('backups') diff --git a/app/Filament/Admin/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php b/app/Filament/Admin/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php index 8574c5a95..1232f69f5 100644 --- a/app/Filament/Admin/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php +++ b/app/Filament/Admin/Resources/ServerResource/RelationManagers/AllocationsRelationManager.php @@ -13,16 +13,15 @@ use Filament\Forms\Components\TextInput; use Filament\Schemas\Components\Utilities\Get; use Filament\Schemas\Components\Utilities\Set; use Filament\Resources\RelationManagers\RelationManager; -use Filament\Support\Exceptions\Halt; -use Filament\Actions\Action; -use Filament\Actions\AssociateAction; -use Filament\Actions\CreateAction; use Filament\Actions\DissociateBulkAction; +use Filament\Actions\CreateAction; +use Filament\Actions\AssociateAction; +use Filament\Actions\Action; +use Filament\Support\Exceptions\Halt; use Filament\Tables\Columns\IconColumn; use Filament\Tables\Columns\TextColumn; use Filament\Tables\Columns\TextInputColumn; use Filament\Tables\Table; -use Illuminate\Database\Eloquent\Collection; /** * @method Server getOwnerRecord() @@ -37,7 +36,6 @@ class AllocationsRelationManager extends RelationManager ->selectCurrentPageOnly() ->recordTitleAttribute('address') ->recordTitle(fn (Allocation $allocation) => $allocation->address) - ->checkIfRecordIsSelectableUsing(fn (Allocation $record) => $record->id !== $this->getOwnerRecord()->allocation_id) ->inverseRelationship('server') ->heading(trans('admin/server.allocations')) ->columns([ @@ -47,6 +45,9 @@ class AllocationsRelationManager extends RelationManager ->label(trans('admin/server.port')), TextInputColumn::make('ip_alias') ->label(trans('admin/server.alias')), + TextInputColumn::make('notes') + ->label(trans('admin/server.notes')) + ->placeholder(trans('admin/server.no_notes')), IconColumn::make('primary') ->icon(fn ($state) => match ($state) { true => 'tabler-star-filled', @@ -56,6 +57,7 @@ class AllocationsRelationManager extends RelationManager true => 'warning', default => 'gray', }) + ->tooltip(fn (Allocation $allocation) => trans('admin/server.' . ($allocation->id === $this->getOwnerRecord()->allocation_id ? 'already' : 'make') . '_primary')) ->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords()) ->default(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id) ->label(trans('admin/server.primary')), @@ -66,7 +68,10 @@ class AllocationsRelationManager extends RelationManager ->action(fn (Allocation $allocation) => $this->getOwnerRecord()->update(['allocation_id' => $allocation->id]) && $this->deselectAllTableRecords()) ->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id), DissociateAction::make() - ->hidden(fn (Allocation $allocation) => $allocation->id === $this->getOwnerRecord()->allocation_id), + ->after(function (Allocation $allocation) { + $allocation->update(['notes' => null]); + $this->getOwnerRecord()->allocation_id && $this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]); + }), ]) ->headerActions([ CreateAction::make()->label(trans('admin/server.create_allocation')) @@ -84,8 +89,7 @@ class AllocationsRelationManager extends RelationManager ->label(trans('admin/server.alias')) ->inlineLabel() ->default(null) - ->helperText(trans('admin/server.alias_helper')) - ->required(false), + ->helperText(trans('admin/server.alias_helper')), TagsInput::make('allocation_ports') ->placeholder('27015, 27017-27019') ->label(trans('admin/server.ports')) @@ -103,22 +107,14 @@ class AllocationsRelationManager extends RelationManager ->preloadRecordSelect() ->recordSelectOptionsQuery(fn ($query) => $query->whereBelongsTo($this->getOwnerRecord()->node)->whereNull('server_id')) ->recordSelectSearchColumns(['ip', 'port']) - ->label(trans('admin/server.add_allocation')), + ->label(trans('admin/server.add_allocation')) + ->after(fn (array $data) => !$this->getOwnerRecord()->allocation_id && $this->getOwnerRecord()->update(['allocation_id' => $data['recordId'][0]])), ]) ->groupedBulkActions([ DissociateBulkAction::make() - ->before(function (DissociateBulkAction $action, Collection $records) { - $records = $records->filter(function ($allocation) { - /** @var Allocation $allocation */ - return $allocation->id !== $this->getOwnerRecord()->allocation_id; - }); - - if ($records->isEmpty()) { - $action->failureNotificationTitle(trans('admin/server.notifications.dissociate_primary'))->failure(); - throw new Halt(); - } - - return $records; + ->after(function () { + Allocation::whereNull('server_id')->update(['notes' => null]); + $this->getOwnerRecord()->allocation_id && $this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]); }), ]); } diff --git a/app/Filament/Admin/Resources/UserResource/RelationManagers/ServersRelationManager.php b/app/Filament/Admin/Resources/UserResource/RelationManagers/ServersRelationManager.php index cf6589f6e..dbd3fef66 100644 --- a/app/Filament/Admin/Resources/UserResource/RelationManagers/ServersRelationManager.php +++ b/app/Filament/Admin/Resources/UserResource/RelationManagers/ServersRelationManager.php @@ -70,8 +70,9 @@ class ServersRelationManager extends RelationManager ->sortable(), SelectColumn::make('allocation.id') ->label(trans('admin/server.primary_allocation')) - ->options(fn (Server $server) => [$server->allocation->id => $server->allocation->address]) - ->selectablePlaceholder(false) + ->disabled() + ->options(fn (Server $server) => $server->allocations->take(1)->mapWithKeys(fn ($allocation) => [$allocation->id => $allocation->address])) + ->placeholder('None') ->sortable(), TextColumn::make('image')->hidden(), TextColumn::make('databases_count') diff --git a/app/Filament/App/Resources/ServerResource/Pages/ListServers.php b/app/Filament/App/Resources/ServerResource/Pages/ListServers.php index 399236a23..747d81050 100644 --- a/app/Filament/App/Resources/ServerResource/Pages/ListServers.php +++ b/app/Filament/App/Resources/ServerResource/Pages/ListServers.php @@ -84,7 +84,8 @@ class ListServers extends ListRecords ->label('') ->badge() ->visibleFrom('md') - ->copyable(request()->isSecure()), + ->copyable(request()->isSecure()) + ->state(fn (Server $server) => $server->allocation->address ?? 'None'), TextColumn::make('cpuUsage') ->label('Resources') ->size(TextSize::Medium) diff --git a/app/Filament/Components/Actions/ImportEggAction.php b/app/Filament/Components/Actions/ImportEggAction.php index c17ccb0da..1883c4add 100644 --- a/app/Filament/Components/Actions/ImportEggAction.php +++ b/app/Filament/Components/Actions/ImportEggAction.php @@ -2,6 +2,7 @@ namespace App\Filament\Components\Actions; +use App\Console\Commands\Egg\UpdateEggIndexCommand; use App\Models\Egg; use App\Services\Eggs\Sharing\EggImporterService; use Closure; @@ -10,10 +11,14 @@ use Filament\Actions\Action; use Filament\Forms\Components\FileUpload; use Filament\Forms\Components\Repeater; use Filament\Forms\Components\TextInput; +use Filament\Forms\Get; +use Filament\Forms\Set; use Filament\Notifications\Notification; use Filament\Schemas\Components\Tabs; use Filament\Schemas\Components\Tabs\Tab; use Illuminate\Support\Arr; +use Illuminate\Support\Facades\Artisan; +use Illuminate\Support\Str; use Livewire\Features\SupportFileUploads\TemporaryUploadedFile; class ImportEggAction extends Action @@ -97,7 +102,28 @@ class ImportEggAction extends Action Tab::make(trans('admin/egg.import.url')) ->icon('tabler-world-upload') ->schema([ + Select::make('github') + ->label(trans('admin/egg.import.github')) + ->options(cache('eggs.index')) + ->selectablePlaceholder(false) + ->searchable() + ->preload() + ->live() + ->hintIcon('tabler-refresh') + ->hintIconTooltip(trans('admin/egg.import.refresh')) + ->hintAction(function () { + Artisan::call(UpdateEggIndexCommand::class); + }) + ->afterStateUpdated(function ($state, Set $set, Get $get) use ($isMultiple) { + if ($state) { + $urls = $isMultiple ? $get('urls') : []; + $urls[Str::uuid()->toString()] = ['url' => $state]; + $set('urls', $urls); + $set('github', null); + } + }), Repeater::make('urls') + ->label('') ->itemLabel(fn (array $state) => str($state['url'])->afterLast('/egg-')->before('.json')->headline()) ->hint(trans('admin/egg.import.url_help')) ->addActionLabel(trans('admin/egg.import.add_url')) diff --git a/app/Filament/Components/Tables/Actions/ImportEggAction.php b/app/Filament/Components/Tables/Actions/ImportEggAction.php index 7988aa9f7..4b50507c3 100644 --- a/app/Filament/Components/Tables/Actions/ImportEggAction.php +++ b/app/Filament/Components/Tables/Actions/ImportEggAction.php @@ -11,9 +11,12 @@ use Filament\Forms\Components\Repeater; use Filament\Schemas\Components\Tabs; use Filament\Schemas\Components\Tabs\Tab; use Filament\Forms\Components\TextInput; +use Filament\Forms\Get; +use Filament\Forms\Set; use Filament\Notifications\Notification; use Filament\Actions\Action; use Illuminate\Support\Arr; +use Illuminate\Support\Str; use Livewire\Features\SupportFileUploads\TemporaryUploadedFile; class ImportEggAction extends Action @@ -97,6 +100,21 @@ class ImportEggAction extends Action Tab::make(trans('admin/egg.import.url')) ->icon('tabler-world-upload') ->schema([ + Select::make('github') + ->label(trans('admin/egg.import.github')) + ->options(cache('eggs.index')) + ->selectablePlaceholder(false) + ->searchable() + ->preload() + ->live() + ->afterStateUpdated(function ($state, Set $set, Get $get) use ($isMultiple) { + if ($state) { + $urls = $isMultiple ? $get('urls') : []; + $urls[Str::uuid()->toString()] = ['url' => $state]; + $set('urls', $urls); + $set('github', null); + } + }), Repeater::make('urls') ->itemLabel(fn (array $state) => str($state['url'])->afterLast('/egg-')->before('.json')->headline()) ->hint(trans('admin/egg.import.url_help')) diff --git a/app/Filament/Server/Resources/AllocationResource.php b/app/Filament/Server/Resources/AllocationResource.php index 43b0f9c9a..37536a01a 100644 --- a/app/Filament/Server/Resources/AllocationResource.php +++ b/app/Filament/Server/Resources/AllocationResource.php @@ -69,11 +69,8 @@ class AllocationResource extends Resource true => 'warning', default => 'gray', }) - ->action(function (Allocation $allocation) use ($server) { - if (auth()->user()->can(PERMISSION::ACTION_ALLOCATION_UPDATE, $server)) { - return $server->update(['allocation_id' => $allocation->id]); - } - }) + ->tooltip(fn (Allocation $allocation) => ($allocation->id === $server->allocation_id ? 'Already' : 'Make') . ' Primary') + ->action(fn (Allocation $allocation) => auth()->user()->can(PERMISSION::ACTION_ALLOCATION_UPDATE, $server) && $server->update(['allocation_id' => $allocation->id])) ->default(fn (Allocation $allocation) => $allocation->id === $server->allocation_id) ->label('Primary'), ]) @@ -82,7 +79,6 @@ class AllocationResource extends Resource ->authorize(fn () => auth()->user()->can(Permission::ACTION_ALLOCATION_DELETE, $server)) ->label('Delete') ->icon('tabler-trash') - ->hidden(fn (Allocation $allocation) => $allocation->id === $server->allocation_id) ->action(function (Allocation $allocation) { Allocation::query()->where('id', $allocation->id)->update([ 'notes' => null, @@ -93,7 +89,8 @@ class AllocationResource extends Resource ->subject($allocation) ->property('allocation', $allocation->address) ->log(); - }), + }) + ->after(fn (Allocation $allocation) => $allocation->id === $server->allocation_id && $server->update(['allocation_id' => $server->allocations()->first()?->id])), ]); } diff --git a/app/Filament/Server/Resources/AllocationResource/Pages/ListAllocations.php b/app/Filament/Server/Resources/AllocationResource/Pages/ListAllocations.php index 83e5ab4c7..5d1e14155 100644 --- a/app/Filament/Server/Resources/AllocationResource/Pages/ListAllocations.php +++ b/app/Filament/Server/Resources/AllocationResource/Pages/ListAllocations.php @@ -37,6 +37,10 @@ class ListAllocations extends ListRecords ->action(function (FindAssignableAllocationService $service) use ($server) { $allocation = $service->handle($server); + if (!$server->allocation_id) { + $server->update(['allocation_id' => $allocation->id]); + } + Activity::event('server:allocation.create') ->subject($allocation) ->property('allocation', $allocation->address) diff --git a/app/Filament/Server/Widgets/ServerOverview.php b/app/Filament/Server/Widgets/ServerOverview.php index 8fa7fad3b..e04d12ad0 100644 --- a/app/Filament/Server/Widgets/ServerOverview.php +++ b/app/Filament/Server/Widgets/ServerOverview.php @@ -23,7 +23,7 @@ class ServerOverview extends StatsOverviewWidget SmallStatBlock::make('Name', $this->server->name) ->copyOnClick(fn () => request()->isSecure()), SmallStatBlock::make('Status', $this->status()), - SmallStatBlock::make('Address', $this->server->allocation->address) + SmallStatBlock::make('Address', $this->server?->allocation->address ?? 'None') ->copyOnClick(fn () => request()->isSecure()), SmallStatBlock::make('CPU', $this->cpuUsage()), SmallStatBlock::make('Memory', $this->memoryUsage()), @@ -68,7 +68,7 @@ class ServerOverview extends StatsOverviewWidget } $latestMemoryUsed = collect(cache()->get("servers.{$this->server->id}.memory_bytes"))->last(default: 0); - $totalMemory = collect(cache()->get("servers.{$this->server->id}.memory_limit_bytes"))->last(default: 0); + $totalMemory = $this->server->memory * 2 ** 20; $used = convert_bytes_to_readable($latestMemoryUsed); $total = convert_bytes_to_readable($totalMemory); diff --git a/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php b/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php index 506d193bb..0abb0dd09 100644 --- a/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php +++ b/app/Http/Controllers/Api/Client/Servers/NetworkAllocationController.php @@ -138,10 +138,6 @@ class NetworkAllocationController extends ClientApiController throw new DisplayException('You cannot delete allocations for this server: no allocation limit is set.'); } - if ($allocation->id === $server->allocation_id) { - throw new DisplayException('You cannot delete the primary allocation for this server.'); - } - Allocation::query()->where('id', $allocation->id)->update([ 'notes' => null, 'server_id' => null, diff --git a/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php b/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php index 11f93b5b6..22fe918ea 100644 --- a/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php +++ b/app/Http/Controllers/Api/Remote/Servers/ServerTransferController.php @@ -51,17 +51,18 @@ class ServerTransferController extends Controller throw new ConflictHttpException('Server is not being transferred.'); } - /** @var Server $server */ - $server = $this->connection->transaction(function () use ($server, $transfer) { - $allocations = array_merge([$transfer->old_allocation], $transfer->old_additional_allocations); - - // Remove the old allocations for the server and re-assign the server to the new - // primary allocation and node. - Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]); - $server->update([ - 'allocation_id' => $transfer->new_allocation, - 'node_id' => $transfer->new_node, - ]); + $data = []; + /** @var \App\Models\Server $server */ + $server = $this->connection->transaction(function () use ($server, $transfer, $data) { + if ($transfer->old_allocation || $transfer->old_additional_allocations) { + $allocations = array_merge([$transfer->old_allocation], $transfer->old_additional_allocations); + // Remove the old allocations for the server and re-assign the server to the new + // primary allocation and node. + Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]); + $data['allocation_id'] = $transfer->new_allocation; + } + $data['node_id'] = $transfer->new_node; + $server->update($data); $server = $server->fresh(); $server->transfer->update(['successful' => true]); @@ -94,8 +95,10 @@ class ServerTransferController extends Controller $this->connection->transaction(function () use (&$transfer) { $transfer->forceFill(['successful' => false])->saveOrFail(); - $allocations = array_merge([$transfer->new_allocation], $transfer->new_additional_allocations); - Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]); + if ($transfer->new_allocation || $transfer->new_additional_allocations) { + $allocations = array_merge([$transfer->new_allocation], $transfer->new_additional_allocations); + Allocation::query()->whereIn('id', $allocations)->update(['server_id' => null]); + } }); return new JsonResponse([], Response::HTTP_NO_CONTENT); diff --git a/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php b/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php index 1c217dd68..fb94dd739 100644 --- a/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php +++ b/app/Http/Requests/Api/Application/Servers/StoreServerRequest.php @@ -176,6 +176,7 @@ class StoreServerRequest extends ApplicationApiRequest $object->setDedicated($this->input('deploy.dedicated_ip', false)); $object->setTags($this->input('deploy.tags', $this->input('deploy.locations', []))); $object->setPorts($this->input('deploy.port_range', [])); + $object->setNode($this->input('deploy.node_id')); return $object; } diff --git a/app/Livewire/ServerEntry.php b/app/Livewire/ServerEntry.php index 35b1a3095..958c6bbbc 100644 --- a/app/Livewire/ServerEntry.php +++ b/app/Livewire/ServerEntry.php @@ -24,7 +24,7 @@ class ServerEntry extends Component style="background-color: #D97706;"> -
Network
{{ $server->allocation->address }}
+{{ $server->allocation?->address ?? 'None' }}