Skip to content

Commit

Permalink
Refactor allocations
Browse files Browse the repository at this point in the history
  • Loading branch information
rmartinoscar committed Oct 24, 2024
1 parent c53ef78 commit 4cd04e8
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 192 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Forms\Set;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Actions\BulkActionGroup;
Expand Down Expand Up @@ -97,54 +96,6 @@ public function table(Table $table): Table
->label('Ports')
->inlineLabel()
->live()
->afterStateUpdated(function ($state, Set $set) {
$ports = collect();
$update = false;
foreach ($state as $portEntry) {
if (!str_contains($portEntry, '-')) {
if (is_numeric($portEntry)) {
$ports->push((int) $portEntry);

continue;
}

// Do not add non numerical ports
$update = true;

continue;
}

$update = true;
[$start, $end] = explode('-', $portEntry);
if (!is_numeric($start) || !is_numeric($end)) {
continue;
}

$start = max((int) $start, 0);
$end = min((int) $end, 2 ** 16 - 1);
foreach (range($start, $end) as $i) {
$ports->push($i);
}
}

$uniquePorts = $ports->unique()->values();
if ($ports->count() > $uniquePorts->count()) {
$update = true;
$ports = $uniquePorts;
}

$sortedPorts = $ports->sort()->values();
if ($sortedPorts->all() !== $ports->all()) {
$update = true;
$ports = $sortedPorts;
}

$ports = $ports->filter(fn ($port) => $port > 1024 && $port < 65535)->values();

if ($update) {
$set('allocation_ports', $ports->all());
}
})
->splitKeys(['Tab', ' ', ','])
->required(),
])
Expand Down
55 changes: 1 addition & 54 deletions app/Filament/Resources/ServerResource/Pages/CreateServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -219,63 +219,10 @@ public function form(Form $form): Form
->label('Ports')
->inlineLabel()
->live()
->afterStateUpdated(function ($state, Set $set) {
$ports = collect();
$update = false;
foreach ($state as $portEntry) {
if (!str_contains($portEntry, '-')) {
if (is_numeric($portEntry)) {
$ports->push((int) $portEntry);

continue;
}

// Do not add non-numerical ports
$update = true;

continue;
}

$update = true;
[$start, $end] = explode('-', $portEntry);
if (!is_numeric($start) || !is_numeric($end)) {
continue;
}

$start = max((int) $start, 0);
$end = min((int) $end, 2 ** 16 - 1);
$range = $start <= $end ? range($start, $end) : range($end, $start);
foreach ($range as $i) {
if ($i > 1024 && $i <= 65535) {
$ports->push($i);
}
}
}

$uniquePorts = $ports->unique()->values();
if ($ports->count() > $uniquePorts->count()) {
$update = true;
$ports = $uniquePorts;
}

$sortedPorts = $ports->sort()->values();
if ($sortedPorts->all() !== $ports->all()) {
$update = true;
$ports = $sortedPorts;
}

if ($update) {
$set('allocation_ports', $ports->all());
}
})
->splitKeys(['Tab', ' ', ','])
->required(),
])
->createOptionUsing(function (array $data, Get $get, AssignmentService $assignmentService): int {
return collect(
$assignmentService->handle(Node::find($get('node_id')), $data)
)->first();
})
->createOptionUsing(fn (array $data, AssignmentService $service): int => collect($service->handle($this->node, $data))->first())
->required(),

Repeater::make('allocation_additional')
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
use Filament\Forms\Components\TagsInput;
use Filament\Forms\Components\TextInput;
use Filament\Forms\Form;
use Filament\Forms\Set;
use Filament\Resources\RelationManagers\RelationManager;
use Filament\Tables;
use Filament\Tables\Actions\Action;
Expand Down Expand Up @@ -93,54 +92,6 @@ public function table(Table $table): Table
->label('Ports')
->inlineLabel()
->live()
->afterStateUpdated(function ($state, Set $set) {
$ports = collect();
$update = false;
foreach ($state as $portEntry) {
if (!str_contains($portEntry, '-')) {
if (is_numeric($portEntry)) {
$ports->push((int) $portEntry);

continue;
}

// Do not add non numerical ports
$update = true;

continue;
}

$update = true;
[$start, $end] = explode('-', $portEntry);
if (!is_numeric($start) || !is_numeric($end)) {
continue;
}

$start = max((int) $start, 0);
$end = min((int) $end, 2 ** 16 - 1);
foreach (range($start, $end) as $i) {
$ports->push($i);
}
}

$uniquePorts = $ports->unique()->values();
if ($ports->count() > $uniquePorts->count()) {
$update = true;
$ports = $uniquePorts;
}

$sortedPorts = $ports->sort()->values();
if ($sortedPorts->all() !== $ports->all()) {
$update = true;
$ports = $sortedPorts;
}

$ports = $ports->filter(fn ($port) => $port > 1024 && $port < 65535)->values();

if ($update) {
$set('allocation_ports', $ports->all());
}
})
->splitKeys(['Tab', ' ', ','])
->required(),
])
Expand Down
92 changes: 52 additions & 40 deletions app/Services/Allocations/AssignmentService.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,8 @@ public function __construct(protected ConnectionInterface $connection)
public function handle(Node $node, array $data, ?Server $server = null): array
{
$explode = explode('/', $data['allocation_ip']);
if (count($explode) !== 1) {
if (!ctype_digit($explode[1]) || ($explode[1] > self::CIDR_MIN_BITS || $explode[1] < self::CIDR_MAX_BITS)) {
throw new CidrOutOfRangeException();
}
if (count($explode) !== 1 && (!ctype_digit($explode[1]) || ($explode[1] > self::CIDR_MIN_BITS || $explode[1] < self::CIDR_MAX_BITS))) {
throw new CidrOutOfRangeException();
}

try {
Expand All @@ -58,62 +56,76 @@ public function handle(Node $node, array $data, ?Server $server = null): array
// an array of records, which is not ideal for this use case, we need a SINGLE
// IP to use, not multiple.
$underlying = gethostbyname($data['allocation_ip']);
$parsed = Network::parse($underlying);
$ip = Network::parse($underlying)
->getIp();
} catch (\Exception $exception) {
throw new DisplayException("Could not parse provided allocation IP address ({$data['allocation_ip']}): {$exception->getMessage()}", $exception);
}

$this->connection->beginTransaction();

$ids = [];
foreach ($parsed as $ip) {
foreach ($data['allocation_ports'] as $port) {
$failed = collect();
$allocation_ports = $data['allocation_ports'];

$ports = collect($allocation_ports)
->flatMap(function ($port) {
if (!is_digit($port) && !preg_match(self::PORT_RANGE_REGEX, $port)) {
throw new InvalidPortMappingException($port);
}

$insertData = [];
if (preg_match(self::PORT_RANGE_REGEX, $port, $matches)) {
$block = range($matches[1], $matches[2]);

if (count($block) > self::PORT_RANGE_LIMIT) {
throw new TooManyPortsInRangeException();
}
if (is_numeric($port)) {
return [(int) $port];
}

if ((int) $matches[1] < self::PORT_FLOOR || (int) $matches[2] > self::PORT_CEIL) {
throw new PortOutOfRangeException();
}
if (str_contains($port, '-')) {
[$start, $end] = explode('-', $port);
if (is_numeric($start) && is_numeric($end)) {
$start = max((int) $start, 1024);
$end = min((int) $end, 65535);

foreach ($block as $unit) {
$insertData[] = [
'node_id' => $node->id,
'ip' => $ip->__toString(),
'port' => (int) $unit,
'ip_alias' => array_get($data, 'allocation_alias'),
'server_id' => $server->id ?? null,
];
}
} else {
if ((int) $port < self::PORT_FLOOR || (int) $port > self::PORT_CEIL) {
throw new PortOutOfRangeException();
return range($start, $end);
}

$insertData[] = [
'node_id' => $node->id,
'ip' => $ip->__toString(),
'port' => (int) $port,
'ip_alias' => array_get($data, 'allocation_alias'),
'server_id' => $server->id ?? null,
];
}

foreach ($insertData as $insert) {
$allocation = Allocation::query()->create($insert);
$ids[] = $allocation->id;
if ((int) $port < self::PORT_FLOOR || (int) $port > self::PORT_CEIL) {
throw new PortOutOfRangeException();
}

return [];
})
->unique()
->sort()
->filter(fn ($port) => $port > 1024 && $port < 65535)
->values();

$insertData = $ports->map(function (int $port) use ($node, $ip, $data, $server) {
return [
'node_id' => $node->id,
'ip' => $ip->__toString(),
'port' => $port,
'ip_alias' => array_get($data, 'allocation_alias'),
'server_id' => $server->id ?? null,
];
});

if ($ports->count() > self::PORT_RANGE_LIMIT) {
throw new TooManyPortsInRangeException();
}

foreach ($insertData as $insert) {
try {
$allocation = Allocation::query()->create($insert);
$ids[] = $allocation->id;
} catch (\Exception) {
$failed->push($insert['port']);
}
}

if ($failed->isNotEmpty()) {
throw new DisplayException("Could not add provided allocation IP address ({$data['allocation_ip']}) with Ports ({$failed->join(', ')}) already exist.");
}

$this->connection->commit();

return $ids;
Expand Down

0 comments on commit 4cd04e8

Please sign in to comment.