patches/Speed/ServerController.php

164 lines
6.2 KiB
PHP

<?php
namespace Convoy\Http\Controllers\Admin;
use Convoy\Enums\Server\Status;
use Convoy\Enums\Server\SuspensionAction;
use Convoy\Exceptions\Repository\Proxmox\ProxmoxConnectionException;
use Convoy\Http\Controllers\ApiController;
use Convoy\Http\Requests\Admin\Servers\Settings\UpdateBuildRequest;
use Convoy\Http\Requests\Admin\Servers\Settings\UpdateGeneralInfoRequest;
use Convoy\Http\Requests\Admin\Servers\StoreServerRequest;
use Convoy\Models\Filters\FiltersServerByAddressPoolId;
use Convoy\Models\Filters\FiltersServerWildcard;
use Convoy\Models\Server;
use Convoy\Services\Servers\CloudinitService;
use Convoy\Services\Servers\NetworkService;
use Convoy\Services\Servers\ServerCreationService;
use Convoy\Services\Servers\ServerDeletionService;
use Convoy\Services\Servers\ServerSuspensionService;
use Convoy\Services\Servers\SyncBuildService;
use Convoy\Transformers\Admin\ServerBuildTransformer;
use Illuminate\Database\ConnectionInterface;
use Illuminate\Http\Request;
use Spatie\QueryBuilder\AllowedFilter;
use Spatie\QueryBuilder\QueryBuilder;
use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
class ServerController extends ApiController
{
public function __construct(
private ConnectionInterface $connection,
private ServerDeletionService $deletionService,
private NetworkService $networkService,
private ServerSuspensionService $suspensionService,
private ServerCreationService $creationService,
private CloudinitService $cloudinitService,
private SyncBuildService $buildModificationService,
)
{
}
public function index(Request $request)
{
$servers = QueryBuilder::for(Server::query())
->with(['addresses', 'user', 'node'])
->defaultSort('-id')
->allowedFilters(
[
AllowedFilter::custom(
'*', new FiltersServerWildcard(),
),
AllowedFilter::custom(
'address_pool_id',
new FiltersServerByAddressPoolId(),
),
AllowedFilter::exact('node_id'),
AllowedFilter::exact('user_id'),
'name',
],
)
->paginate(min($request->query('per_page', 50), 100))->appends(
$request->query(),
);
return fractal($servers, new ServerBuildTransformer())->parseIncludes($request->include)
->respond();
}
public function show(Request $request, Server $server)
{
$server->load(['addresses', 'user', 'node']);
return fractal($server, new ServerBuildTransformer())->parseIncludes($request->include)
->respond();
}
public function store(StoreServerRequest $request)
{
$server = $this->creationService->handle($request->validated());
$server->load(['addresses', 'user', 'node']);
return fractal($server, new ServerBuildTransformer())->parseIncludes(['user', 'node'])
->respond();
}
public function update(UpdateGeneralInfoRequest $request, Server $server)
{
$this->connection->transaction(function () use ($request, $server) {
if ($request->hostname !== $server->hostname && !empty($request->hostname)) {
try {
$this->cloudinitService->updateHostname($server, $request->hostname);
} catch (ProxmoxConnectionException) {
throw new ServiceUnavailableHttpException(
message: "Server {$server->uuid} failed to sync hostname.",
);
}
}
$server->update($request->validated());
});
$server->load(['addresses', 'user', 'node']);
return fractal($server, new ServerBuildTransformer())->parseIncludes(['user', 'node'])
->respond();
}
public function updateBuild(UpdateBuildRequest $request, Server $server)
{
$validated = $request->validated();
// Handle address_ids separately
$addressIds = $validated['address_ids'] ?? null;
unset($validated['address_ids']);
// Ensure rate_limit is always present in update data to avoid validation errors
if (!array_key_exists('rate_limit', $validated)) {
$validated['rate_limit'] = $server->rate_limit ?? null;
}
// Update server with validated data
$server->update($validated);
$this->networkService->updateAddresses($server, $addressIds ?? []);
try {
$this->buildModificationService->handle($server);
} catch (ProxmoxConnectionException $e) {
// do nothing
}
$server->load(['addresses', 'user', 'node']);
return fractal($server, new ServerBuildTransformer())->parseIncludes(['user', 'node'])
->respond();
}
public function suspend(Server $server)
{
$this->suspensionService->toggle($server);
return $this->returnNoContent();
}
public function unsuspend(Server $server)
{
$this->suspensionService->toggle($server, SuspensionAction::UNSUSPEND);
return $this->returnNoContent();
}
public function destroy(Request $request, Server $server)
{
$this->connection->transaction(function () use ($server, $request) {
$server->update(['status' => Status::DELETING->value]);
$this->deletionService->handle($server, $request->input('no_purge', false));
});
return $this->returnNoContent();
}
}