Add test coverage for allocation auto-assignment service
This commit is contained in:
parent
d493685518
commit
6cb21fb920
2 changed files with 185 additions and 3 deletions
|
@ -5,7 +5,6 @@ namespace Pterodactyl\Services\Allocations;
|
||||||
use Webmozart\Assert\Assert;
|
use Webmozart\Assert\Assert;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use Pterodactyl\Models\Allocation;
|
use Pterodactyl\Models\Allocation;
|
||||||
use Pterodactyl\Exceptions\DisplayException;
|
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\AutoAllocationNotEnabledException;
|
use Pterodactyl\Exceptions\Service\Allocation\AutoAllocationNotEnabledException;
|
||||||
use Pterodactyl\Exceptions\Service\Allocation\NoAutoAllocationSpaceAvailableException;
|
use Pterodactyl\Exceptions\Service\Allocation\NoAutoAllocationSpaceAvailableException;
|
||||||
|
|
||||||
|
@ -64,6 +63,10 @@ class FindAssignableAllocationService
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Create a new allocation on the server's node with a random port from the defined range
|
||||||
|
* in the settings. If there are no matches in that range, or something is wrong with the
|
||||||
|
* range information provided an exception will be raised.
|
||||||
|
*
|
||||||
* @param \Pterodactyl\Models\Server $server
|
* @param \Pterodactyl\Models\Server $server
|
||||||
* @return \Pterodactyl\Models\Allocation
|
* @return \Pterodactyl\Models\Allocation
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,179 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Pterodactyl\Tests\Integration\Services\Allocations;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
use InvalidArgumentException;
|
||||||
|
use Pterodactyl\Models\Allocation;
|
||||||
|
use Pterodactyl\Tests\Integration\IntegrationTestCase;
|
||||||
|
use Pterodactyl\Services\Allocations\FindAssignableAllocationService;
|
||||||
|
use Pterodactyl\Exceptions\Service\Allocation\AutoAllocationNotEnabledException;
|
||||||
|
use Pterodactyl\Exceptions\Service\Allocation\NoAutoAllocationSpaceAvailableException;
|
||||||
|
|
||||||
|
class FindAssignableAllocationServiceTest extends IntegrationTestCase
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Setup tests.
|
||||||
|
*/
|
||||||
|
public function setUp(): void
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
config()->set('pterodactyl.client_features.allocations.enabled', true);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_start', 0);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_end', 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that an unassigned allocation is prefered rather than creating an entirely new
|
||||||
|
* allocation for the server.
|
||||||
|
*/
|
||||||
|
public function testExistingAllocationIsPreferred()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
|
||||||
|
$created = factory(Allocation::class)->create([
|
||||||
|
'node_id' => $server->node_id,
|
||||||
|
'ip' => $server->allocation->ip,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->getService()->handle($server);
|
||||||
|
|
||||||
|
$this->assertSame($created->id, $response->id);
|
||||||
|
$this->assertSame($server->allocation->ip, $response->ip);
|
||||||
|
$this->assertSame($server->node_id, $response->node_id);
|
||||||
|
$this->assertSame($server->id, $response->server_id);
|
||||||
|
$this->assertNotSame($server->allocation_id, $response->id);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that a new allocation is created if there is not a free one available.
|
||||||
|
*/
|
||||||
|
public function testNewAllocationIsCreatedIfOneIsNotFound()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_start', 5000);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_end', 5005);
|
||||||
|
|
||||||
|
$response = $this->getService()->handle($server);
|
||||||
|
$this->assertSame($server->id, $response->server_id);
|
||||||
|
$this->assertSame($server->allocation->ip, $response->ip);
|
||||||
|
$this->assertSame($server->node_id, $response->node_id);
|
||||||
|
$this->assertNotSame($server->allocation_id, $response->id);
|
||||||
|
$this->assertTrue($response->port >= 5000 && $response->port <= 5005);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that a currently assigned port is never assigned to a server.
|
||||||
|
*/
|
||||||
|
public function testOnlyPortNotInUseIsCreated()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
$server2 = $this->createServerModel(['node_id' => $server->node_id]);
|
||||||
|
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_start', 5000);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_end', 5001);
|
||||||
|
|
||||||
|
factory(Allocation::class)->create([
|
||||||
|
'server_id' => $server2->id,
|
||||||
|
'node_id' => $server->node_id,
|
||||||
|
'ip' => $server->allocation->ip,
|
||||||
|
'port' => 5000,
|
||||||
|
]);
|
||||||
|
|
||||||
|
$response = $this->getService()->handle($server);
|
||||||
|
$this->assertSame(5001, $response->port);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExceptionIsThrownIfNoMoreAllocationsCanBeCreatedInRange()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
$server2 = $this->createServerModel(['node_id' => $server->node_id]);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_start', 5000);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_end', 5005);
|
||||||
|
|
||||||
|
for ($i = 5000; $i <= 5005; $i++) {
|
||||||
|
factory(Allocation::class)->create([
|
||||||
|
'ip' => $server->allocation->ip,
|
||||||
|
'port' => $i,
|
||||||
|
'node_id' => $server->node_id,
|
||||||
|
'server_id' => $server2->id,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->expectException(NoAutoAllocationSpaceAvailableException::class);
|
||||||
|
$this->expectExceptionMessage('Cannot assign additional allocation: no more space available on node.');
|
||||||
|
|
||||||
|
$this->getService()->handle($server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that we only auto-allocate from the current server's IP address space, and not a random
|
||||||
|
* IP address available on that node.
|
||||||
|
*/
|
||||||
|
public function testExceptionIsThrownIfOnlyFreePortIsOnADifferentIp()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
|
||||||
|
factory(Allocation::class)->times(5)->create(['node_id' => $server->node_id]);
|
||||||
|
|
||||||
|
$this->expectException(NoAutoAllocationSpaceAvailableException::class);
|
||||||
|
$this->expectExceptionMessage('Cannot assign additional allocation: no more space available on node.');
|
||||||
|
|
||||||
|
$this->getService()->handle($server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExceptionIsThrownIfStartOrEndRangeIsNotDefined()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
|
||||||
|
$this->expectException(NoAutoAllocationSpaceAvailableException::class);
|
||||||
|
$this->expectExceptionMessage('Cannot assign additional allocation: no more space available on node.');
|
||||||
|
|
||||||
|
$this->getService()->handle($server);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExceptionIsThrownIfStartOrEndRangeIsNotNumeric()
|
||||||
|
{
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_start', 'hodor');
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_end', 10);
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->getService()->handle($server);
|
||||||
|
$this->assertTrue(false, 'This assertion should not be reached.');
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
|
||||||
|
$this->assertSame('Expected an integerish value. Got: string', $exception->getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_start', 10);
|
||||||
|
config()->set('pterodactyl.client_features.allocations.range_end', 'hodor');
|
||||||
|
|
||||||
|
try {
|
||||||
|
$this->getService()->handle($server);
|
||||||
|
$this->assertTrue(false, 'This assertion should not be reached.');
|
||||||
|
} catch (Exception $exception) {
|
||||||
|
$this->assertInstanceOf(InvalidArgumentException::class, $exception);
|
||||||
|
$this->assertSame('Expected an integerish value. Got: string', $exception->getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public function testExceptionIsThrownIfFeatureIsNotEnabled()
|
||||||
|
{
|
||||||
|
config()->set('pterodactyl.client_features.allocations.enabled', false);
|
||||||
|
$server = $this->createServerModel();
|
||||||
|
|
||||||
|
$this->expectException(AutoAllocationNotEnabledException::class);
|
||||||
|
|
||||||
|
$this->getService()->handle($server);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return \Pterodactyl\Services\Allocations\FindAssignableAllocationService
|
||||||
|
*/
|
||||||
|
private function getService()
|
||||||
|
{
|
||||||
|
return $this->app->make(FindAssignableAllocationService::class);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue