2017-07-23 01:15:01 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Tests\Unit\Services\Servers;
|
|
|
|
|
|
|
|
use Mockery as m;
|
2017-08-05 22:26:30 +00:00
|
|
|
use Tests\TestCase;
|
2018-02-10 20:01:49 +00:00
|
|
|
use Pterodactyl\Models\Egg;
|
2020-06-25 05:18:48 +00:00
|
|
|
use GuzzleHttp\Psr7\Request;
|
2017-10-27 04:49:54 +00:00
|
|
|
use Pterodactyl\Models\User;
|
2017-10-08 20:44:28 +00:00
|
|
|
use Tests\Traits\MocksUuids;
|
2017-10-27 04:49:54 +00:00
|
|
|
use Pterodactyl\Models\Server;
|
2018-02-10 20:01:49 +00:00
|
|
|
use Pterodactyl\Models\Allocation;
|
2017-10-27 04:49:54 +00:00
|
|
|
use Tests\Traits\MocksRequestException;
|
2020-06-25 05:18:48 +00:00
|
|
|
use GuzzleHttp\Exception\ConnectException;
|
2017-10-06 05:16:22 +00:00
|
|
|
use Illuminate\Database\ConnectionInterface;
|
2018-02-10 20:01:49 +00:00
|
|
|
use Pterodactyl\Models\Objects\DeploymentObject;
|
2020-06-25 05:18:48 +00:00
|
|
|
use Pterodactyl\Repositories\Eloquent\EggRepository;
|
|
|
|
use Pterodactyl\Repositories\Eloquent\ServerRepository;
|
2017-08-27 20:10:51 +00:00
|
|
|
use Pterodactyl\Services\Servers\ServerCreationService;
|
2020-06-25 05:18:48 +00:00
|
|
|
use Pterodactyl\Services\Servers\ServerDeletionService;
|
|
|
|
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
|
2017-07-23 01:15:01 +00:00
|
|
|
use Pterodactyl\Services\Servers\VariableValidatorService;
|
2020-06-25 05:18:48 +00:00
|
|
|
use Pterodactyl\Repositories\Eloquent\AllocationRepository;
|
2018-01-28 23:14:14 +00:00
|
|
|
use Pterodactyl\Services\Deployment\FindViableNodesService;
|
2020-06-25 05:18:48 +00:00
|
|
|
use Pterodactyl\Repositories\Eloquent\ServerVariableRepository;
|
2018-01-28 23:14:14 +00:00
|
|
|
use Pterodactyl\Services\Deployment\AllocationSelectionService;
|
2020-06-25 05:18:48 +00:00
|
|
|
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
2017-10-06 05:16:22 +00:00
|
|
|
use Pterodactyl\Services\Servers\ServerConfigurationStructureService;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
2017-10-06 05:16:22 +00:00
|
|
|
/**
|
|
|
|
* @preserveGlobalState disabled
|
|
|
|
*/
|
2017-08-27 20:10:51 +00:00
|
|
|
class ServerCreationServiceTest extends TestCase
|
2017-07-23 01:15:01 +00:00
|
|
|
{
|
2017-10-27 04:49:54 +00:00
|
|
|
use MocksRequestException, MocksUuids;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2017-10-27 04:49:54 +00:00
|
|
|
private $allocationRepository;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
2018-01-28 23:14:14 +00:00
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2018-01-28 23:14:14 +00:00
|
|
|
*/
|
|
|
|
private $allocationSelectionService;
|
|
|
|
|
2017-07-23 01:15:01 +00:00
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-10-06 05:16:22 +00:00
|
|
|
*/
|
2017-10-27 04:49:54 +00:00
|
|
|
private $configurationStructureService;
|
2017-10-06 05:16:22 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-10-06 05:16:22 +00:00
|
|
|
*/
|
2017-10-27 04:49:54 +00:00
|
|
|
private $connection;
|
2017-10-06 05:16:22 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2017-10-27 04:49:54 +00:00
|
|
|
private $daemonServerRepository;
|
2017-08-13 19:55:09 +00:00
|
|
|
|
2017-07-23 01:15:01 +00:00
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-08-13 19:55:09 +00:00
|
|
|
*/
|
2018-01-28 23:14:14 +00:00
|
|
|
private $eggRepository;
|
2017-08-13 19:55:09 +00:00
|
|
|
|
2017-07-23 01:15:01 +00:00
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2018-01-28 23:14:14 +00:00
|
|
|
private $findViableNodesService;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2017-10-27 04:49:54 +00:00
|
|
|
private $repository;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2017-10-27 04:49:54 +00:00
|
|
|
private $serverVariableRepository;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2020-06-25 05:18:48 +00:00
|
|
|
private $validatorService;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
|
|
|
/**
|
2020-06-25 05:18:48 +00:00
|
|
|
* @var \Mockery\MockInterface
|
2017-07-23 01:15:01 +00:00
|
|
|
*/
|
2020-06-25 05:18:48 +00:00
|
|
|
private $serverDeletionService;
|
2017-07-23 01:15:01 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Setup tests.
|
|
|
|
*/
|
2020-05-09 16:00:52 +00:00
|
|
|
public function setUp(): void
|
2017-07-23 01:15:01 +00:00
|
|
|
{
|
|
|
|
parent::setUp();
|
|
|
|
|
2020-06-25 05:18:48 +00:00
|
|
|
$this->allocationRepository = m::mock(AllocationRepository::class);
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->allocationSelectionService = m::mock(AllocationSelectionService::class);
|
2017-10-06 05:16:22 +00:00
|
|
|
$this->configurationStructureService = m::mock(ServerConfigurationStructureService::class);
|
|
|
|
$this->connection = m::mock(ConnectionInterface::class);
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->findViableNodesService = m::mock(FindViableNodesService::class);
|
2017-07-23 01:15:01 +00:00
|
|
|
$this->validatorService = m::mock(VariableValidatorService::class);
|
2020-06-25 05:18:48 +00:00
|
|
|
$this->eggRepository = m::mock(EggRepository::class);
|
|
|
|
$this->repository = m::mock(ServerRepository::class);
|
|
|
|
$this->serverVariableRepository = m::mock(ServerVariableRepository::class);
|
|
|
|
$this->daemonServerRepository = m::mock(DaemonServerRepository::class);
|
|
|
|
$this->serverDeletionService = m::mock(ServerDeletionService::class);
|
2017-07-23 01:15:01 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test core functionality of the creation process.
|
|
|
|
*/
|
|
|
|
public function testCreateShouldHitAllOfTheNecessaryServicesAndStoreTheServer()
|
|
|
|
{
|
2017-10-27 04:49:54 +00:00
|
|
|
$model = factory(Server::class)->make([
|
|
|
|
'uuid' => $this->getKnownUuid(),
|
|
|
|
]);
|
2017-07-23 01:15:01 +00:00
|
|
|
|
2017-10-06 05:16:22 +00:00
|
|
|
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
2018-03-04 04:20:53 +00:00
|
|
|
$this->repository->shouldReceive('isUniqueUuidCombo')
|
|
|
|
->once()
|
|
|
|
->with($this->getKnownUuid(), substr($this->getKnownUuid(), 0, 8))
|
|
|
|
->andReturn(true);
|
|
|
|
|
2017-10-08 20:44:28 +00:00
|
|
|
$this->repository->shouldReceive('create')->with(m::subset([
|
|
|
|
'uuid' => $this->getKnownUuid(),
|
2018-03-04 04:20:53 +00:00
|
|
|
'uuidShort' => substr($this->getKnownUuid(), 0, 8),
|
2017-10-27 04:49:54 +00:00
|
|
|
'node_id' => $model->node_id,
|
2018-02-10 20:01:49 +00:00
|
|
|
'allocation_id' => $model->allocation_id,
|
2017-10-27 04:49:54 +00:00
|
|
|
'owner_id' => $model->owner_id,
|
|
|
|
'nest_id' => $model->nest_id,
|
|
|
|
'egg_id' => $model->egg_id,
|
|
|
|
]))->once()->andReturn($model);
|
2017-07-23 01:15:01 +00:00
|
|
|
|
2018-01-05 04:49:50 +00:00
|
|
|
$this->allocationRepository->shouldReceive('assignAllocationsToServer')->with($model->id, [$model->allocation_id])->once()->andReturn(1);
|
2017-10-06 05:16:22 +00:00
|
|
|
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->validatorService->shouldReceive('setUserLevel')->with(User::USER_LEVEL_ADMIN)->once()->andReturnSelf();
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->validatorService->shouldReceive('handle')->with($model->egg_id, [])->once()->andReturn(
|
|
|
|
collect([(object) ['id' => 123, 'value' => 'var1-value']])
|
|
|
|
);
|
2017-10-06 05:16:22 +00:00
|
|
|
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->serverVariableRepository->shouldReceive('insert')->with([
|
|
|
|
[
|
|
|
|
'server_id' => $model->id,
|
|
|
|
'variable_id' => 123,
|
|
|
|
'variable_value' => 'var1-value',
|
|
|
|
],
|
2018-01-05 04:49:50 +00:00
|
|
|
])->once()->andReturn(true);
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->configurationStructureService->shouldReceive('handle')->with($model)->once()->andReturn(['test' => 'struct']);
|
|
|
|
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->daemonServerRepository->shouldReceive('setServer')->with($model)->once()->andReturnSelf();
|
2020-06-25 05:18:48 +00:00
|
|
|
$this->daemonServerRepository->shouldReceive('create')->with(['test' => 'struct'])->once();
|
2017-10-06 05:16:22 +00:00
|
|
|
$this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull();
|
2017-07-23 01:15:01 +00:00
|
|
|
|
2018-01-28 23:14:14 +00:00
|
|
|
$response = $this->getService()->handle($model->toArray());
|
2017-07-23 01:15:01 +00:00
|
|
|
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->assertSame($model, $response);
|
2017-07-23 01:15:01 +00:00
|
|
|
}
|
2017-08-13 19:55:09 +00:00
|
|
|
|
2018-02-10 20:01:49 +00:00
|
|
|
/**
|
|
|
|
* Test that optional parameters get auto-filled correctly on the model.
|
|
|
|
*/
|
|
|
|
public function testDataIsAutoFilled()
|
|
|
|
{
|
|
|
|
$model = factory(Server::class)->make(['uuid' => $this->getKnownUuid()]);
|
|
|
|
$allocationModel = factory(Allocation::class)->make(['node_id' => $model->node_id]);
|
|
|
|
$eggModel = factory(Egg::class)->make(['nest_id' => $model->nest_id]);
|
|
|
|
|
|
|
|
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs();
|
|
|
|
$this->allocationRepository->shouldReceive('setColumns->find')->once()->with($model->allocation_id)->andReturn($allocationModel);
|
|
|
|
$this->eggRepository->shouldReceive('setColumns->find')->once()->with($model->egg_id)->andReturn($eggModel);
|
|
|
|
|
|
|
|
$this->validatorService->shouldReceive('setUserLevel->handle')->once()->andReturn(collect([]));
|
2018-03-04 04:20:53 +00:00
|
|
|
$this->repository->shouldReceive('isUniqueUuidCombo')
|
|
|
|
->once()
|
|
|
|
->with($this->getKnownUuid(), substr($this->getKnownUuid(), 0, 8))
|
|
|
|
->andReturn(true);
|
|
|
|
|
|
|
|
$this->repository->shouldReceive('create')->with(m::subset([
|
2018-02-10 20:01:49 +00:00
|
|
|
'uuid' => $this->getKnownUuid(),
|
2018-03-04 04:20:53 +00:00
|
|
|
'uuidShort' => substr($this->getKnownUuid(), 0, 8),
|
2018-02-10 20:01:49 +00:00
|
|
|
'node_id' => $model->node_id,
|
|
|
|
'allocation_id' => $model->allocation_id,
|
|
|
|
'nest_id' => $model->nest_id,
|
|
|
|
'egg_id' => $model->egg_id,
|
|
|
|
]))->andReturn($model);
|
|
|
|
|
|
|
|
$this->allocationRepository->shouldReceive('assignAllocationsToServer')->once()->with($model->id, [$model->allocation_id]);
|
|
|
|
$this->configurationStructureService->shouldReceive('handle')->once()->with($model)->andReturn([]);
|
|
|
|
|
|
|
|
$this->daemonServerRepository->shouldReceive('setServer->create')->once();
|
|
|
|
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
|
|
|
|
|
|
$this->getService()->handle(
|
|
|
|
collect($model->toArray())->except(['node_id', 'nest_id'])->toArray()
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Test that an auto-deployment object is used correctly if passed.
|
|
|
|
*/
|
|
|
|
public function testAutoDeploymentObject()
|
|
|
|
{
|
|
|
|
$model = factory(Server::class)->make(['uuid' => $this->getKnownUuid()]);
|
|
|
|
$deploymentObject = new DeploymentObject();
|
|
|
|
$deploymentObject->setPorts(['25565']);
|
|
|
|
$deploymentObject->setDedicated(false);
|
|
|
|
$deploymentObject->setLocations([1]);
|
|
|
|
|
|
|
|
$this->connection->shouldReceive('beginTransaction')->once()->withNoArgs();
|
|
|
|
|
|
|
|
$this->findViableNodesService->shouldReceive('setLocations')->once()->with($deploymentObject->getLocations())->andReturnSelf();
|
|
|
|
$this->findViableNodesService->shouldReceive('setDisk')->once()->with($model->disk)->andReturnSelf();
|
|
|
|
$this->findViableNodesService->shouldReceive('setMemory')->once()->with($model->memory)->andReturnSelf();
|
|
|
|
$this->findViableNodesService->shouldReceive('handle')->once()->withNoArgs()->andReturn([1, 2]);
|
|
|
|
|
|
|
|
$allocationModel = factory(Allocation::class)->make([
|
|
|
|
'id' => $model->allocation_id,
|
|
|
|
'node_id' => $model->node_id,
|
|
|
|
]);
|
|
|
|
$this->allocationSelectionService->shouldReceive('setDedicated')->once()->with($deploymentObject->isDedicated())->andReturnSelf();
|
|
|
|
$this->allocationSelectionService->shouldReceive('setNodes')->once()->with([1, 2])->andReturnSelf();
|
|
|
|
$this->allocationSelectionService->shouldReceive('setPorts')->once()->with($deploymentObject->getPorts())->andReturnSelf();
|
|
|
|
$this->allocationSelectionService->shouldReceive('handle')->once()->withNoArgs()->andReturn($allocationModel);
|
|
|
|
|
|
|
|
$this->validatorService->shouldReceive('setUserLevel->handle')->once()->andReturn(collect([]));
|
2018-03-04 04:20:53 +00:00
|
|
|
$this->repository->shouldReceive('isUniqueUuidCombo')
|
|
|
|
->once()
|
|
|
|
->with($this->getKnownUuid(), substr($this->getKnownUuid(), 0, 8))
|
|
|
|
->andReturn(true);
|
|
|
|
|
|
|
|
$this->repository->shouldReceive('create')->with(m::subset([
|
2018-02-10 20:01:49 +00:00
|
|
|
'uuid' => $this->getKnownUuid(),
|
2018-03-04 04:20:53 +00:00
|
|
|
'uuidShort' => substr($this->getKnownUuid(), 0, 8),
|
2018-02-10 20:01:49 +00:00
|
|
|
'node_id' => $model->node_id,
|
|
|
|
'allocation_id' => $model->allocation_id,
|
|
|
|
'nest_id' => $model->nest_id,
|
|
|
|
'egg_id' => $model->egg_id,
|
|
|
|
]))->andReturn($model);
|
|
|
|
|
|
|
|
$this->allocationRepository->shouldReceive('assignAllocationsToServer')->once()->with($model->id, [$model->allocation_id]);
|
|
|
|
$this->configurationStructureService->shouldReceive('handle')->once()->with($model)->andReturn([]);
|
|
|
|
|
|
|
|
$this->daemonServerRepository->shouldReceive('setServer->create')->once();
|
|
|
|
$this->connection->shouldReceive('commit')->once()->withNoArgs()->andReturnNull();
|
|
|
|
|
|
|
|
$this->getService()->handle(
|
|
|
|
collect($model->toArray())->except(['allocation_id', 'node_id'])->toArray(), $deploymentObject
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2017-08-13 19:55:09 +00:00
|
|
|
/**
|
|
|
|
* Test handling of node timeout or other daemon error.
|
|
|
|
*/
|
|
|
|
public function testExceptionShouldBeThrownIfTheRequestFails()
|
|
|
|
{
|
2020-06-25 05:18:48 +00:00
|
|
|
$this->expectException(DaemonConnectionException::class);
|
2017-10-27 04:49:54 +00:00
|
|
|
|
|
|
|
$model = factory(Server::class)->make([
|
|
|
|
'uuid' => $this->getKnownUuid(),
|
2017-08-13 19:55:09 +00:00
|
|
|
]);
|
|
|
|
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->connection->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull();
|
2018-03-04 04:20:53 +00:00
|
|
|
$this->repository->shouldReceive('isUniqueUuidCombo')->once()->andReturn(true);
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->repository->shouldReceive('create')->once()->andReturn($model);
|
2018-01-05 04:49:50 +00:00
|
|
|
$this->allocationRepository->shouldReceive('assignAllocationsToServer')->once()->andReturn(1);
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->validatorService->shouldReceive('setUserLevel')->once()->andReturnSelf();
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->validatorService->shouldReceive('handle')->once()->andReturn(collect([]));
|
|
|
|
$this->configurationStructureService->shouldReceive('handle')->once()->andReturn([]);
|
2018-01-06 00:27:47 +00:00
|
|
|
|
2020-06-25 05:18:48 +00:00
|
|
|
$this->connection->expects('commit')->withNoArgs();
|
|
|
|
|
|
|
|
$this->daemonServerRepository->shouldReceive('setServer')->with($model)->once()->andThrow(
|
|
|
|
new DaemonConnectionException(
|
|
|
|
new ConnectException('', new Request('GET', 'test'))
|
|
|
|
)
|
|
|
|
);
|
|
|
|
|
|
|
|
$this->serverDeletionService->expects('withForce')->with(true)->andReturnSelf();
|
|
|
|
$this->serverDeletionService->expects('handle')->with($model);
|
2017-08-13 19:55:09 +00:00
|
|
|
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->getService()->handle($model->toArray());
|
2017-08-13 19:55:09 +00:00
|
|
|
}
|
2017-10-27 04:49:54 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Return an instance of the service with mocked dependencies.
|
|
|
|
*
|
|
|
|
* @return \Pterodactyl\Services\Servers\ServerCreationService
|
|
|
|
*/
|
|
|
|
private function getService(): ServerCreationService
|
|
|
|
{
|
|
|
|
return new ServerCreationService(
|
|
|
|
$this->allocationRepository,
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->allocationSelectionService,
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->connection,
|
|
|
|
$this->daemonServerRepository,
|
2018-01-28 23:14:14 +00:00
|
|
|
$this->eggRepository,
|
|
|
|
$this->findViableNodesService,
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->configurationStructureService,
|
2020-06-25 05:18:48 +00:00
|
|
|
$this->serverDeletionService,
|
2017-10-27 04:49:54 +00:00
|
|
|
$this->repository,
|
|
|
|
$this->serverVariableRepository,
|
|
|
|
$this->validatorService
|
|
|
|
);
|
|
|
|
}
|
2017-07-23 01:15:01 +00:00
|
|
|
}
|