Replace allocation repository

This commit is contained in:
Lance Pioch 2022-10-23 02:02:58 -04:00
parent 860b2d890b
commit cd49324d46
10 changed files with 95 additions and 164 deletions

View file

@ -1,19 +0,0 @@
<?php
namespace Pterodactyl\Contracts\Repository;
use Pterodactyl\Models\Allocation;
interface AllocationRepositoryInterface extends RepositoryInterface
{
/**
* Return all the allocations that exist for a node that are not currently
* allocated.
*/
public function getUnassignedAllocationIds(int $node): array;
/**
* Return a single allocation from those meeting the requirements.
*/
public function getRandomAllocation(array $nodes, array $ports, bool $dedicated = false): ?Allocation;
}

View file

@ -14,7 +14,6 @@ use Pterodactyl\Repositories\Eloquent\ServerRepository;
use Pterodactyl\Traits\Controllers\JavascriptInjection; use Pterodactyl\Traits\Controllers\JavascriptInjection;
use Pterodactyl\Services\Helpers\SoftwareVersionService; use Pterodactyl\Services\Helpers\SoftwareVersionService;
use Pterodactyl\Repositories\Eloquent\LocationRepository; use Pterodactyl\Repositories\Eloquent\LocationRepository;
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
class NodeViewController extends Controller class NodeViewController extends Controller
{ {
@ -24,7 +23,6 @@ class NodeViewController extends Controller
* NodeViewController constructor. * NodeViewController constructor.
*/ */
public function __construct( public function __construct(
private AllocationRepository $allocationRepository,
private LocationRepository $locationRepository, private LocationRepository $locationRepository,
private NodeRepository $repository, private NodeRepository $repository,
private ServerRepository $serverRepository, private ServerRepository $serverRepository,

View file

@ -23,7 +23,6 @@ use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Node\AllocationFormRequest; use Pterodactyl\Http\Requests\Admin\Node\AllocationFormRequest;
use Pterodactyl\Services\Allocations\AllocationDeletionService; use Pterodactyl\Services\Allocations\AllocationDeletionService;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Http\Requests\Admin\Node\AllocationAliasFormRequest; use Pterodactyl\Http\Requests\Admin\Node\AllocationAliasFormRequest;
class NodesController extends Controller class NodesController extends Controller
@ -34,7 +33,6 @@ class NodesController extends Controller
public function __construct( public function __construct(
protected AlertsMessageBag $alert, protected AlertsMessageBag $alert,
protected AllocationDeletionService $allocationDeletionService, protected AllocationDeletionService $allocationDeletionService,
protected AllocationRepositoryInterface $allocationRepository,
protected AssignmentService $assignmentService, protected AssignmentService $assignmentService,
protected CacheRepository $cache, protected CacheRepository $cache,
protected NodeCreationService $creationService, protected NodeCreationService $creationService,
@ -125,11 +123,12 @@ class NodesController extends Controller
*/ */
public function allocationRemoveBlock(Request $request, int $node): RedirectResponse public function allocationRemoveBlock(Request $request, int $node): RedirectResponse
{ {
$this->allocationRepository->deleteWhere([ /** @var Node $node */
['node_id', '=', $node], $node = Node::query()->findOrFail($node);
['server_id', '=', null], $node->allocations()
['ip', '=', $request->input('ip')], ->where('ip', $request->input('ip'))
]); ->whereNull('server_id')
->delete();
$this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => $request->input('ip')])) $this->alert->success(trans('admin/node.notices.unallocated_deleted', ['ip' => $request->input('ip')]))
->flash(); ->flash();
@ -140,14 +139,12 @@ class NodesController extends Controller
/** /**
* Sets an alias for a specific allocation on a node. * Sets an alias for a specific allocation on a node.
* *
* @throws \Pterodactyl\Exceptions\Model\DataValidationException
* @throws \Pterodactyl\Exceptions\Repository\RecordNotFoundException
*/ */
public function allocationSetAlias(AllocationAliasFormRequest $request): \Symfony\Component\HttpFoundation\Response public function allocationSetAlias(AllocationAliasFormRequest $request): \Symfony\Component\HttpFoundation\Response
{ {
$this->allocationRepository->update($request->input('allocation_id'), [ $allocation = Allocation::query()->findOrFail($request->input('allocation_id'));
'ip_alias' => (empty($request->input('alias'))) ? null : $request->input('alias'), $alias = (empty($request->input('alias'))) ? null : $request->input('alias');
]); $allocation->update(['ip_alias' => $alias]);
return response('', 204); return response('', 204);
} }

View file

@ -3,15 +3,16 @@
namespace Pterodactyl\Http\Controllers\Admin\Servers; namespace Pterodactyl\Http\Controllers\Admin\Servers;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Pterodactyl\Models\Node;
use Pterodactyl\Models\Server; use Pterodactyl\Models\Server;
use Prologue\Alerts\AlertsMessageBag; use Pterodactyl\Models\Allocation;
use Illuminate\Http\RedirectResponse; use Illuminate\Http\RedirectResponse;
use Prologue\Alerts\AlertsMessageBag;
use Pterodactyl\Models\ServerTransfer; use Pterodactyl\Models\ServerTransfer;
use Pterodactyl\Http\Controllers\Controller; use Pterodactyl\Http\Controllers\Controller;
use Pterodactyl\Services\Servers\TransferService; use Pterodactyl\Services\Servers\TransferService;
use Pterodactyl\Repositories\Eloquent\NodeRepository; use Pterodactyl\Repositories\Eloquent\NodeRepository;
use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository; use Pterodactyl\Repositories\Wings\DaemonConfigurationRepository;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
class ServerTransferController extends Controller class ServerTransferController extends Controller
{ {
@ -20,7 +21,6 @@ class ServerTransferController extends Controller
*/ */
public function __construct( public function __construct(
private AlertsMessageBag $alert, private AlertsMessageBag $alert,
private AllocationRepositoryInterface $allocationRepository,
private NodeRepository $nodeRepository, private NodeRepository $nodeRepository,
private TransferService $transferService, private TransferService $transferService,
private DaemonConfigurationRepository $daemonConfigurationRepository private DaemonConfigurationRepository $daemonConfigurationRepository
@ -87,7 +87,12 @@ class ServerTransferController extends Controller
$allocations = $additional_allocations; $allocations = $additional_allocations;
$allocations[] = $allocation_id; $allocations[] = $allocation_id;
$unassigned = $this->allocationRepository->getUnassignedAllocationIds($node_id); /** @var Node $node */
$node = Node::query()->findOrFail($node_id);
$unassigned = $node->allocations()
->whereNull('server_id')
->pluck('id')
->toArray();
$updateIds = []; $updateIds = [];
foreach ($allocations as $allocation) { foreach ($allocations as $allocation) {
@ -99,7 +104,9 @@ class ServerTransferController extends Controller
} }
if (!empty($updateIds)) { if (!empty($updateIds)) {
$this->allocationRepository->updateWhereIn('id', $updateIds, ['server_id' => $server->id]); Allocation::query()
->whereIn('id', $updateIds)
->update(['server_id' => $server->id]);
} }
} }
} }

View file

@ -30,7 +30,6 @@ use Pterodactyl\Services\Databases\DatabaseManagementService;
use Illuminate\Contracts\Config\Repository as ConfigRepository; use Illuminate\Contracts\Config\Repository as ConfigRepository;
use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; use Pterodactyl\Contracts\Repository\ServerRepositoryInterface;
use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Services\Servers\ServerConfigurationStructureService; use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest; use Pterodactyl\Http\Requests\Admin\Servers\Databases\StoreServerDatabaseRequest;
@ -41,7 +40,6 @@ class ServersController extends Controller
*/ */
public function __construct( public function __construct(
protected AlertsMessageBag $alert, protected AlertsMessageBag $alert,
protected AllocationRepositoryInterface $allocationRepository,
protected BuildModificationService $buildModificationService, protected BuildModificationService $buildModificationService,
protected ConfigRepository $config, protected ConfigRepository $config,
protected DaemonServerRepository $daemonServerRepository, protected DaemonServerRepository $daemonServerRepository,

View file

@ -16,7 +16,6 @@ use Pterodactyl\Repositories\Eloquent\DatabaseRepository;
use Pterodactyl\Repositories\Eloquent\LocationRepository; use Pterodactyl\Repositories\Eloquent\LocationRepository;
use Pterodactyl\Repositories\Eloquent\ScheduleRepository; use Pterodactyl\Repositories\Eloquent\ScheduleRepository;
use Pterodactyl\Repositories\Eloquent\SettingsRepository; use Pterodactyl\Repositories\Eloquent\SettingsRepository;
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
use Pterodactyl\Contracts\Repository\EggRepositoryInterface; use Pterodactyl\Contracts\Repository\EggRepositoryInterface;
use Pterodactyl\Repositories\Eloquent\EggVariableRepository; use Pterodactyl\Repositories\Eloquent\EggVariableRepository;
use Pterodactyl\Contracts\Repository\NestRepositoryInterface; use Pterodactyl\Contracts\Repository\NestRepositoryInterface;
@ -33,7 +32,6 @@ use Pterodactyl\Contracts\Repository\DatabaseRepositoryInterface;
use Pterodactyl\Contracts\Repository\LocationRepositoryInterface; use Pterodactyl\Contracts\Repository\LocationRepositoryInterface;
use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface; use Pterodactyl\Contracts\Repository\ScheduleRepositoryInterface;
use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface; use Pterodactyl\Contracts\Repository\SettingsRepositoryInterface;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface; use Pterodactyl\Contracts\Repository\EggVariableRepositoryInterface;
use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface; use Pterodactyl\Contracts\Repository\DatabaseHostRepositoryInterface;
use Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface; use Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface;
@ -46,7 +44,6 @@ class RepositoryServiceProvider extends ServiceProvider
public function register() public function register()
{ {
// Eloquent Repositories // Eloquent Repositories
$this->app->bind(AllocationRepositoryInterface::class, AllocationRepository::class);
$this->app->bind(ApiKeyRepositoryInterface::class, ApiKeyRepository::class); $this->app->bind(ApiKeyRepositoryInterface::class, ApiKeyRepository::class);
$this->app->bind(DatabaseRepositoryInterface::class, DatabaseRepository::class); $this->app->bind(DatabaseRepositoryInterface::class, DatabaseRepository::class);
$this->app->bind(DatabaseHostRepositoryInterface::class, DatabaseHostRepository::class); $this->app->bind(DatabaseHostRepositoryInterface::class, DatabaseHostRepository::class);

View file

@ -1,100 +0,0 @@
<?php
namespace Pterodactyl\Repositories\Eloquent;
use Pterodactyl\Models\Allocation;
use Illuminate\Database\Eloquent\Builder;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
class AllocationRepository extends EloquentRepository implements AllocationRepositoryInterface
{
/**
* Return the model backing this repository.
*/
public function model(): string
{
return Allocation::class;
}
/**
* Return all the allocations that exist for a node that are not currently
* allocated.
*/
public function getUnassignedAllocationIds(int $node): array
{
return Allocation::query()->select('id')
->whereNull('server_id')
->where('node_id', $node)
->get()
->pluck('id')
->toArray();
}
/**
* Return a concatenated result set of node ips that already have at least one
* server assigned to that IP. This allows for filtering out sets for
* dedicated allocation IPs.
*
* If an array of nodes is passed the results will be limited to allocations
* in those nodes.
*/
protected function getDiscardableDedicatedAllocations(array $nodes = []): array
{
$query = Allocation::query()->selectRaw('CONCAT_WS("-", node_id, ip) as result');
if (!empty($nodes)) {
$query->whereIn('node_id', $nodes);
}
return $query->whereNotNull('server_id')
->groupByRaw('CONCAT(node_id, ip)')
->get()
->pluck('result')
->toArray();
}
/**
* Return a single allocation from those meeting the requirements.
*/
public function getRandomAllocation(array $nodes, array $ports, bool $dedicated = false): ?Allocation
{
$query = Allocation::query()->whereNull('server_id');
if (!empty($nodes)) {
$query->whereIn('node_id', $nodes);
}
if (!empty($ports)) {
$query->where(function (Builder $inner) use ($ports) {
$whereIn = [];
foreach ($ports as $port) {
if (is_array($port)) {
$inner->orWhereBetween('port', $port);
continue;
}
$whereIn[] = $port;
}
if (!empty($whereIn)) {
$inner->orWhereIn('port', $whereIn);
}
});
}
// If this allocation should not be shared with any other servers get
// the data and modify the query as necessary,
if ($dedicated) {
$discard = $this->getDiscardableDedicatedAllocations($nodes);
if (!empty($discard)) {
$query->whereNotIn(
$this->getBuilder()->raw('CONCAT_WS("-", node_id, ip)'),
$discard
);
}
}
return $query->inRandomOrder()->first();
}
}

View file

@ -3,18 +3,10 @@
namespace Pterodactyl\Services\Allocations; namespace Pterodactyl\Services\Allocations;
use Pterodactyl\Models\Allocation; use Pterodactyl\Models\Allocation;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException; use Pterodactyl\Exceptions\Service\Allocation\ServerUsingAllocationException;
class AllocationDeletionService class AllocationDeletionService
{ {
/**
* AllocationDeletionService constructor.
*/
public function __construct(private AllocationRepositoryInterface $repository)
{
}
/** /**
* Delete an allocation from the database only if it does not have a server * Delete an allocation from the database only if it does not have a server
* that is actively attached to it. * that is actively attached to it.
@ -27,6 +19,6 @@ class AllocationDeletionService
throw new ServerUsingAllocationException(trans('exceptions.allocations.server_using')); throw new ServerUsingAllocationException(trans('exceptions.allocations.server_using'));
} }
return $this->repository->delete($allocation->id); return $allocation->delete();
} }
} }

View file

@ -4,10 +4,10 @@ namespace Pterodactyl\Services\Allocations;
use Exception; use Exception;
use IPTools\Network; use IPTools\Network;
use Pterodactyl\Models\Allocation;
use Pterodactyl\Models\Node; use Pterodactyl\Models\Node;
use Illuminate\Database\ConnectionInterface; use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException; use Pterodactyl\Exceptions\Service\Allocation\CidrOutOfRangeException;
use Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException; use Pterodactyl\Exceptions\Service\Allocation\PortOutOfRangeException;
use Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException; use Pterodactyl\Exceptions\Service\Allocation\InvalidPortMappingException;
@ -25,7 +25,7 @@ class AssignmentService
/** /**
* AssignmentService constructor. * AssignmentService constructor.
*/ */
public function __construct(protected AllocationRepositoryInterface $repository, protected ConnectionInterface $connection) public function __construct(protected ConnectionInterface $connection)
{ {
} }
@ -101,7 +101,7 @@ class AssignmentService
]; ];
} }
$this->repository->insertIgnore($insertData); Allocation::query()->insertOrIgnore($insertData);
} }
} }

View file

@ -2,10 +2,10 @@
namespace Pterodactyl\Services\Deployment; namespace Pterodactyl\Services\Deployment;
use Illuminate\Database\Eloquent\Builder;
use Pterodactyl\Models\Allocation; use Pterodactyl\Models\Allocation;
use Pterodactyl\Exceptions\DisplayException; use Pterodactyl\Exceptions\DisplayException;
use Pterodactyl\Services\Allocations\AssignmentService; use Pterodactyl\Services\Allocations\AssignmentService;
use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface;
use Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException; use Pterodactyl\Exceptions\Service\Deployment\NoViableAllocationException;
class AllocationSelectionService class AllocationSelectionService
@ -16,13 +16,6 @@ class AllocationSelectionService
protected array $ports = []; protected array $ports = [];
/**
* AllocationSelectionService constructor.
*/
public function __construct(private AllocationRepositoryInterface $repository)
{
}
/** /**
* Toggle if the selected allocation should be the only allocation belonging * Toggle if the selected allocation should be the only allocation belonging
* to the given IP address. If true an allocation will not be selected if an IP * to the given IP address. If true an allocation will not be selected if an IP
@ -84,7 +77,7 @@ class AllocationSelectionService
*/ */
public function handle(): Allocation public function handle(): Allocation
{ {
$allocation = $this->repository->getRandomAllocation($this->nodes, $this->ports, $this->dedicated); $allocation = $this->getRandomAllocation($this->nodes, $this->ports, $this->dedicated);
if (is_null($allocation)) { if (is_null($allocation)) {
throw new NoViableAllocationException(trans('exceptions.deployment.no_viable_allocations')); throw new NoViableAllocationException(trans('exceptions.deployment.no_viable_allocations'));
@ -92,4 +85,72 @@ class AllocationSelectionService
return $allocation; return $allocation;
} }
/**
* Return a single allocation from those meeting the requirements.
*/
private function getRandomAllocation(array $nodes = [], array $ports = [], bool $dedicated = false): ?Allocation
{
$query = Allocation::query()->whereNull('server_id');
if (!empty($nodes)) {
$query->whereIn('node_id', $nodes);
}
if (!empty($ports)) {
$query->where(function (Builder $inner) use ($ports) {
$whereIn = [];
foreach ($ports as $port) {
if (is_array($port)) {
$inner->orWhereBetween('port', $port);
continue;
}
$whereIn[] = $port;
}
if (!empty($whereIn)) {
$inner->orWhereIn('port', $whereIn);
}
});
}
// If this allocation should not be shared with any other servers get
// the data and modify the query as necessary,
if ($dedicated) {
$discard = $this->getDiscardableDedicatedAllocations($nodes);
if (!empty($discard)) {
$query->whereNotIn(
$this->getBuilder()->raw('CONCAT_WS("-", node_id, ip)'),
$discard
);
}
}
return $query->inRandomOrder()->first();
}
/**
* Return a concatenated result set of node ips that already have at least one
* server assigned to that IP. This allows for filtering out sets for
* dedicated allocation IPs.
*
* If an array of nodes is passed the results will be limited to allocations
* in those nodes.
*/
private function getDiscardableDedicatedAllocations(array $nodes = []): array
{
$query = Allocation::query()->selectRaw('CONCAT_WS("-", node_id, ip) as result');
if (!empty($nodes)) {
$query->whereIn('node_id', $nodes);
}
return $query->whereNotNull('server_id')
->groupByRaw('CONCAT(node_id, ip)')
->get()
->pluck('result')
->toArray();
}
} }