Move the primary allocation when it is removed from a server
This commit is contained in:
1 parent
72779c7ea6
commit
ddaef93768
6 files changed
+82
-4
No files matched your search
+2
-2
@@ -117,7 +117,7 @@ class AllocationsRelationManager extends RelationManager
|
||||
->after(function (Allocation $allocation) {
|
||||
$allocation->update(Allocation::RELEASE_ATTRIBUTES);
|
||||
|
||||
if (!$this->getOwnerRecord()->allocation_id) {
|
||||
if (!$this->getOwnerRecord()->allocation_id || $this->getOwnerRecord()->allocation_id === $allocation->id) {
|
||||
$this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]);
|
||||
}
|
||||
}),
|
||||
@@ -128,7 +128,7 @@ class AllocationsRelationManager extends RelationManager
|
||||
->after(function (Collection $records) {
|
||||
Allocation::whereIn('id', $records->pluck('id'))->update(Allocation::RELEASE_ATTRIBUTES);
|
||||
|
||||
if (!$this->getOwnerRecord()->allocation_id) {
|
||||
if (!$this->getOwnerRecord()->allocation_id || $records->contains('id', $this->getOwnerRecord()->allocation_id)) {
|
||||
$this->getOwnerRecord()->update(['allocation_id' => $this->getOwnerRecord()->allocations()->first()?->id]);
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -139,6 +139,10 @@ class NetworkAllocationController extends ClientApiController
|
||||
|
||||
Allocation::query()->where('id', $allocation->id)->update(Allocation::RELEASE_ATTRIBUTES);
|
||||
|
||||
if ($allocation->id === $server->allocation_id) {
|
||||
$server->update(['allocation_id' => $server->allocations()->first()?->id]);
|
||||
}
|
||||
|
||||
Activity::event('server:allocation.delete')
|
||||
->subject($allocation)
|
||||
->property('allocation', $allocation->address)
|
||||
|
||||
@@ -231,11 +231,14 @@ class Server extends Model implements HasAvatar, Validatable
|
||||
*/
|
||||
public function getAllocationMappings(): array
|
||||
{
|
||||
if (!$this->allocation) {
|
||||
$allocations = $this->allocations->where('node_id', $this->node_id);
|
||||
|
||||
// Daemon expects a map here, and an empty array would be encoded as a JSON list.
|
||||
if (!$this->allocation || $allocations->isEmpty()) {
|
||||
return ['' => []];
|
||||
}
|
||||
|
||||
return $this->allocations->where('node_id', $this->node_id)->groupBy('ip')->map(function ($item) {
|
||||
return $allocations->groupBy('ip')->map(function ($item) {
|
||||
return $item->pluck('port');
|
||||
})->toArray();
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use App\Enums\RolePermissionModels;
|
||||
use App\Filament\Admin\Resources\Servers\Pages\CreateServer;
|
||||
use App\Filament\Admin\Resources\Servers\Pages\EditServer;
|
||||
use App\Filament\Admin\Resources\Servers\RelationManagers\AllocationsRelationManager;
|
||||
use App\Models\Allocation;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Node;
|
||||
@@ -88,6 +89,45 @@ it('can delete a server', function () {
|
||||
$this->assertDatabaseMissing('servers', ['id' => $server->id]);
|
||||
});
|
||||
|
||||
it('moves the primary allocation when it is removed from a server', function () {
|
||||
$server = createServerModel();
|
||||
$primary = $server->allocation;
|
||||
$other = Allocation::factory()->forServer($server)->create();
|
||||
|
||||
livewire(AllocationsRelationManager::class, ['ownerRecord' => $server, 'pageClass' => EditServer::class])
|
||||
->callAction(TestAction::make('dissociate')->table($primary));
|
||||
|
||||
expect($primary->refresh()->server_id)->toBeNull()
|
||||
->and($server->refresh()->allocation_id)->toBe($other->id);
|
||||
});
|
||||
|
||||
it('clears the primary allocation when the last allocation is removed from a server', function () {
|
||||
$server = createServerModel();
|
||||
$primary = $server->allocation;
|
||||
|
||||
livewire(AllocationsRelationManager::class, ['ownerRecord' => $server, 'pageClass' => EditServer::class])
|
||||
->callAction(TestAction::make('dissociate')->table($primary));
|
||||
|
||||
$server->refresh();
|
||||
|
||||
expect($server->allocation_id)->toBeNull()
|
||||
->and(json_encode($server->getAllocationMappings()))->toBe('{"":[]}');
|
||||
});
|
||||
|
||||
it('moves the primary allocation when it is removed from a server in bulk', function () {
|
||||
$server = createServerModel();
|
||||
$primary = $server->allocation;
|
||||
[$removed, $kept] = Allocation::factory()->count(2)->forServer($server)->create();
|
||||
|
||||
livewire(AllocationsRelationManager::class, ['ownerRecord' => $server, 'pageClass' => EditServer::class])
|
||||
->selectTableRecords([$primary->id, $removed->id])
|
||||
->callAction(TestAction::make('dissociate')->table()->bulk());
|
||||
|
||||
expect($primary->refresh()->server_id)->toBeNull()
|
||||
->and($removed->refresh()->server_id)->toBeNull()
|
||||
->and($server->refresh()->allocation_id)->toBe($kept->id);
|
||||
});
|
||||
|
||||
it('non root admin without permission cannot create servers', function () {
|
||||
$role = Role::factory()->create(['name' => 'Egg Viewer', 'guard_name' => 'web']);
|
||||
// Egg permission is on purpose, we check the wrong permissions.
|
||||
|
||||
@@ -57,6 +57,25 @@ class DeleteAllocationTest extends ClientApiIntegrationTestCase
|
||||
$this->actingAs($user)->deleteJson($this->link($allocation))->assertStatus(Response::HTTP_NO_CONTENT);
|
||||
|
||||
$this->assertDatabaseHas('allocations', ['id' => $allocation->id, 'server_id' => null, 'notes' => null]);
|
||||
$this->assertNull($server->refresh()->allocation_id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test that deleting the primary allocation makes one of the remaining allocations
|
||||
* the new primary allocation for the server.
|
||||
*/
|
||||
public function test_primary_allocation_is_moved_when_deleted_from_server(): void
|
||||
{
|
||||
/** @var Server $server */
|
||||
[$user, $server] = $this->generateTestAccount();
|
||||
$server->update(['allocation_limit' => 2]);
|
||||
|
||||
$allocation = $server->allocation;
|
||||
$other = Allocation::factory()->forServer($server)->create();
|
||||
|
||||
$this->actingAs($user)->deleteJson($this->link($allocation))->assertStatus(Response::HTTP_NO_CONTENT);
|
||||
|
||||
$this->assertSame($other->id, $server->refresh()->allocation_id);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,9 +2,11 @@
|
||||
|
||||
namespace App\Tests\Unit\Models;
|
||||
|
||||
use App\Models\Allocation;
|
||||
use App\Models\Node;
|
||||
use App\Models\Server;
|
||||
use App\Tests\TestCase;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
|
||||
class ServerTest extends TestCase
|
||||
@@ -44,6 +46,16 @@ class ServerTest extends TestCase
|
||||
$this->assertSame('sftp://user%20name.abcdefgh@node.example.com:2022/data/', $server->getSftpUrl('user name', '/data'));
|
||||
}
|
||||
|
||||
public function test_allocation_mappings_stay_an_object_when_the_server_has_no_allocations(): void
|
||||
{
|
||||
$server = new Server();
|
||||
$server->node_id = 1;
|
||||
$server->setRelation('allocation', new Allocation(['node_id' => 1, 'ip' => '127.0.0.1', 'port' => 25565]));
|
||||
$server->setRelation('allocations', new Collection());
|
||||
|
||||
$this->assertSame('{"":[]}', json_encode($server->getAllocationMappings()));
|
||||
}
|
||||
|
||||
private function serverWithNode(string $fqdn = 'node.example.com', ?string $sftpAlias = null): Server
|
||||
{
|
||||
$node = new Node();
|
||||
|
||||
Reference in new issue
Block a user