diff --git a/app/Services/Servers/ReinstallServerService.php b/app/Services/Servers/ReinstallServerService.php index 27955c475..a68e97110 100644 --- a/app/Services/Servers/ReinstallServerService.php +++ b/app/Services/Servers/ReinstallServerService.php @@ -4,8 +4,8 @@ namespace Pterodactyl\Services\Servers; use Pterodactyl\Models\Server; use Illuminate\Database\ConnectionInterface; +use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Repositories\Wings\DaemonServerRepository; -use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; class ReinstallServerService { @@ -17,27 +17,27 @@ class ReinstallServerService /** * @var \Illuminate\Database\ConnectionInterface */ - private $database; + private $connection; /** - * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface + * @var \Pterodactyl\Repositories\Eloquent\ServerRepository */ private $repository; /** * ReinstallService constructor. * - * @param \Illuminate\Database\ConnectionInterface $database + * @param \Illuminate\Database\ConnectionInterface $connection * @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository - * @param \Pterodactyl\Contracts\Repository\ServerRepositoryInterface $repository + * @param \Pterodactyl\Repositories\Eloquent\ServerRepository $repository */ public function __construct( - ConnectionInterface $database, + ConnectionInterface $connection, DaemonServerRepository $daemonServerRepository, - ServerRepositoryInterface $repository + ServerRepository $repository ) { $this->daemonServerRepository = $daemonServerRepository; - $this->database = $database; + $this->connection = $connection; $this->repository = $repository; } @@ -51,14 +51,14 @@ class ReinstallServerService */ public function reinstall(Server $server) { - $this->database->transaction(function () use ($server) { - $this->repository->withoutFreshModel()->update($server->id, [ + return $this->connection->transaction(function () use ($server) { + $updated = $this->repository->update($server->id, [ 'installed' => Server::STATUS_INSTALLING, ]); $this->daemonServerRepository->setServer($server)->reinstall(); - }); - return $server->refresh(); + return $updated; + }); } } diff --git a/app/Services/Servers/ServerCreationService.php b/app/Services/Servers/ServerCreationService.php index cce242e5a..b84bed7c5 100644 --- a/app/Services/Servers/ServerCreationService.php +++ b/app/Services/Servers/ServerCreationService.php @@ -310,8 +310,6 @@ class ServerCreationService return $allocation->node_id; } - /** @noinspection PhpDocMissingThrowsInspection */ - /** * Create a unique UUID and UUID-Short combo for a server. * @@ -319,7 +317,6 @@ class ServerCreationService */ private function generateUniqueUuidCombo(): string { - /** @noinspection PhpUnhandledExceptionInspection */ $uuid = Uuid::uuid4()->toString(); if (! $this->repository->isUniqueUuidCombo($uuid, substr($uuid, 0, 8))) { diff --git a/tests/Unit/Services/Packs/ExportPackServiceTest.php b/tests/Unit/Services/Packs/ExportPackServiceTest.php index 031e1fb39..936b7b06d 100644 --- a/tests/Unit/Services/Packs/ExportPackServiceTest.php +++ b/tests/Unit/Services/Packs/ExportPackServiceTest.php @@ -17,6 +17,7 @@ use Pterodactyl\Models\Pack; use Illuminate\Contracts\Filesystem\Factory; use Pterodactyl\Services\Packs\ExportPackService; use Pterodactyl\Contracts\Repository\PackRepositoryInterface; +use Pterodactyl\Exceptions\Service\Pack\ZipArchiveCreationException; class ExportPackServiceTest extends TestCase { @@ -132,11 +133,11 @@ class ExportPackServiceTest extends TestCase /** * Test that an exception is thrown when a ZipArchive cannot be created. - * - * @expectedException \Pterodactyl\Exceptions\Service\Pack\ZipArchiveCreationException */ public function testExceptionIsThrownIfZipArchiveCannotBeCreated() { + $this->expectException(ZipArchiveCreationException::class); + $this->setupTestData(); $this->getFunctionMock('\\Pterodactyl\\Services\\Packs', 'tempnam') diff --git a/tests/Unit/Services/Servers/ReinstallServerServiceTest.php b/tests/Unit/Services/Servers/ReinstallServerServiceTest.php index 8bd95f0b8..22cc35199 100644 --- a/tests/Unit/Services/Servers/ReinstallServerServiceTest.php +++ b/tests/Unit/Services/Servers/ReinstallServerServiceTest.php @@ -9,48 +9,30 @@ namespace Tests\Unit\Services\Servers; -use Exception; use Mockery as m; use Tests\TestCase; -use GuzzleHttp\Psr7\Response; use Pterodactyl\Models\Server; -use GuzzleHttp\Exception\RequestException; use Illuminate\Database\ConnectionInterface; +use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Services\Servers\ReinstallServerService; -use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; -use Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface as DaemonServerRepositoryInterface; +use Pterodactyl\Repositories\Wings\DaemonServerRepository; class ReinstallServerServiceTest extends TestCase { /** - * @var \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface + * @var \Pterodactyl\Repositories\Wings\DaemonServerRepository */ - protected $daemonServerRepository; + private $daemonServerRepository; /** * @var \Illuminate\Database\ConnectionInterface */ - protected $database; - - /** - * @var \GuzzleHttp\Exception\RequestException - */ - protected $exception; + private $connection; /** * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface */ - protected $repository; - - /** - * @var \Pterodactyl\Models\Server - */ - protected $server; - - /** - * @var \Pterodactyl\Services\Servers\ReinstallServerService - */ - protected $service; + private $repository; /** * Setup tests. @@ -59,18 +41,9 @@ class ReinstallServerServiceTest extends TestCase { parent::setUp(); - $this->daemonServerRepository = m::mock(DaemonServerRepositoryInterface::class); - $this->database = m::mock(ConnectionInterface::class); - $this->exception = m::mock(RequestException::class)->makePartial(); - $this->repository = m::mock(ServerRepositoryInterface::class); - - $this->server = factory(Server::class)->make(['node_id' => 1]); - - $this->service = new ReinstallServerService( - $this->database, - $this->daemonServerRepository, - $this->repository - ); + $this->repository = m::mock(ServerRepository::class); + $this->connection = m::mock(ConnectionInterface::class); + $this->daemonServerRepository = m::mock(DaemonServerRepository::class); } /** @@ -78,70 +51,32 @@ class ReinstallServerServiceTest extends TestCase */ public function testServerShouldBeReinstalledWhenModelIsPassed() { - $this->repository->shouldNotReceive('find'); + /** @var \Pterodactyl\Models\Server $server */ + $server = factory(Server::class)->make(['id' => 123]); + $updated = clone $server; + $updated->installed = Server::STATUS_INSTALLING; - $this->database->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); - $this->repository->shouldReceive('withoutFreshModel->update')->with($this->server->id, [ - 'installed' => 0, - ], true, true)->once()->andReturnNull(); + $this->connection->expects('transaction')->with(m::on(function ($closure) use ($updated) { + return $closure() instanceof Server; + }))->andReturn($updated); - $this->daemonServerRepository->shouldReceive('setServer')->with($this->server)->once()->andReturnSelf() - ->shouldReceive('reinstall')->withNoArgs()->once()->andReturn(new Response); - $this->database->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); + $this->repository->expects('update')->with($server->id, [ + 'installed' => Server::STATUS_INSTALLING, + ])->andReturns($updated); - $this->service->reinstall($this->server); + $this->daemonServerRepository->expects('setServer')->with($server)->andReturnSelf(); + $this->daemonServerRepository->expects('reinstall')->withNoArgs(); + + $this->assertSame($updated, $this->getService()->reinstall($server)); } /** - * Test that a server is reinstalled when the ID of the server is passed to the function. + * @return \Pterodactyl\Services\Servers\ReinstallServerService */ - public function testServerShouldBeReinstalledWhenServerIdIsPassed() + private function getService() { - $this->repository->shouldReceive('find')->with($this->server->id)->once()->andReturn($this->server); - - $this->database->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); - $this->repository->shouldReceive('withoutFreshModel->update')->with($this->server->id, [ - 'installed' => 0, - ], true, true)->once()->andReturnNull(); - - $this->daemonServerRepository->shouldReceive('setServer')->with($this->server)->once()->andReturnSelf() - ->shouldReceive('reinstall')->withNoArgs()->once()->andReturn(new Response); - $this->database->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); - - $this->service->reinstall($this->server->id); - } - - /** - * Test that an exception thrown by guzzle is rendered as a displayable exception. - * - * @expectedException \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException - */ - public function testExceptionThrownByGuzzleShouldBeReRenderedAsDisplayable() - { - $this->database->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); - $this->repository->shouldReceive('withoutFreshModel->update')->with($this->server->id, [ - 'installed' => 0, - ], true, true)->once()->andReturnNull(); - - $this->daemonServerRepository->shouldReceive('setServer')->with($this->server)->once()->andThrow($this->exception); - - $this->service->reinstall($this->server); - } - - /** - * Test that an exception thrown by something other than guzzle is not transformed to a displayable. - * - * @expectedException \Exception - */ - public function testExceptionNotThrownByGuzzleShouldNotBeTransformedToDisplayable() - { - $this->database->shouldReceive('beginTransaction')->withNoArgs()->once()->andReturnNull(); - $this->repository->shouldReceive('withoutFreshModel->update')->with($this->server->id, [ - 'installed' => 0, - ], true, true)->once()->andReturnNull(); - - $this->daemonServerRepository->shouldReceive('setServer')->with($this->server)->once()->andThrow(new Exception()); - - $this->service->reinstall($this->server); + return new ReinstallServerService( + $this->connection, $this->daemonServerRepository, $this->repository + ); } } diff --git a/tests/Unit/Services/Servers/ServerConfigurationStructureServiceTest.php b/tests/Unit/Services/Servers/ServerConfigurationStructureServiceTest.php index aa63cfa4b..e6c301b92 100644 --- a/tests/Unit/Services/Servers/ServerConfigurationStructureServiceTest.php +++ b/tests/Unit/Services/Servers/ServerConfigurationStructureServiceTest.php @@ -40,53 +40,62 @@ class ServerConfigurationStructureServiceTest extends TestCase */ public function testCorrectStructureIsReturned() { + /** @var \Pterodactyl\Models\Server $model */ $model = factory(Server::class)->make(); $model->setRelation('pack', null); $model->setRelation('allocation', factory(Allocation::class)->make()); $model->setRelation('allocations', collect(factory(Allocation::class)->times(2)->make())); $model->setRelation('egg', factory(Egg::class)->make()); - $portListing = $model->allocations->groupBy('ip')->map(function ($item) { - return $item->pluck('port'); - })->toArray(); - - $this->repository->shouldReceive('getDataForCreation')->with($model)->once()->andReturn($model); - $this->environment->shouldReceive('handle')->with($model)->once()->andReturn(['environment_array']); + $this->environment->expects('handle')->with($model)->andReturn(['environment_array']); $response = $this->getService()->handle($model); $this->assertNotEmpty($response); $this->assertArrayNotHasKey('user', $response); $this->assertArrayNotHasKey('keys', $response); + $this->assertArrayHasKey('uuid', $response); + $this->assertArrayHasKey('suspended', $response); + $this->assertArrayHasKey('environment', $response); + $this->assertArrayHasKey('invocation', $response); $this->assertArrayHasKey('build', $response); $this->assertArrayHasKey('service', $response); - $this->assertArrayHasKey('rebuild', $response); - $this->assertArrayHasKey('suspended', $response); + $this->assertArrayHasKey('container', $response); + $this->assertArrayHasKey('allocations', $response); - $this->assertArraySubset([ + $this->assertSame([ 'default' => [ 'ip' => $model->allocation->ip, 'port' => $model->allocation->port, ], - ], $response['build'], true, 'Assert server default allocation is correct.'); - $this->assertArraySubset(['ports' => $portListing], $response['build'], true, 'Assert server ports are correct.'); - $this->assertArraySubset([ - 'env' => ['environment_array'], - 'swap' => (int) $model->swap, - 'io' => (int) $model->io, - 'cpu' => (int) $model->cpu, - 'disk' => (int) $model->disk, - 'image' => $model->image, - ], $response['build'], true, 'Assert server build data is correct.'); + 'mappings' => $model->getAllocationMappings(), + ], $response['allocations']); - $this->assertArraySubset([ + $this->assertSame([ + 'memory_limit' => $model->memory, + 'swap' => $model->swap, + 'io_weight' => $model->io, + 'cpu_limit' => $model->cpu, + 'threads' => $model->threads, + 'disk_space' => $model->disk, + ], $response['build']); + + $this->assertSame([ 'egg' => $model->egg->uuid, 'pack' => null, 'skip_scripts' => $model->skip_scripts, ], $response['service']); - $this->assertFalse($response['rebuild']); - $this->assertSame((int) $model->suspended, $response['suspended']); + $this->assertSame([ + 'image' => $model->image, + 'oom_disabled' => $model->oom_disabled, + 'requires_rebuild' => false, + ], $response['container']); + + $this->assertSame($model->uuid, $response['uuid']); + $this->assertSame((bool) $model->suspended, $response['suspended']); + $this->assertSame(['environment_array'], $response['environment']); + $this->assertSame($model->startup, $response['invocation']); } /** diff --git a/tests/Unit/Services/Servers/ServerCreationServiceTest.php b/tests/Unit/Services/Servers/ServerCreationServiceTest.php index 27c7892b6..4efdd926d 100644 --- a/tests/Unit/Services/Servers/ServerCreationServiceTest.php +++ b/tests/Unit/Services/Servers/ServerCreationServiceTest.php @@ -5,24 +5,27 @@ namespace Tests\Unit\Services\Servers; use Mockery as m; use Tests\TestCase; use Pterodactyl\Models\Egg; +use GuzzleHttp\Psr7\Request; use Pterodactyl\Models\User; use Tests\Traits\MocksUuids; use Pterodactyl\Models\Server; use Pterodactyl\Models\Allocation; use Tests\Traits\MocksRequestException; +use GuzzleHttp\Exception\ConnectException; use Illuminate\Database\ConnectionInterface; use Pterodactyl\Models\Objects\DeploymentObject; +use Pterodactyl\Repositories\Eloquent\EggRepository; +use Pterodactyl\Repositories\Eloquent\ServerRepository; use Pterodactyl\Services\Servers\ServerCreationService; +use Pterodactyl\Services\Servers\ServerDeletionService; +use Pterodactyl\Repositories\Wings\DaemonServerRepository; use Pterodactyl\Services\Servers\VariableValidatorService; +use Pterodactyl\Repositories\Eloquent\AllocationRepository; use Pterodactyl\Services\Deployment\FindViableNodesService; -use Pterodactyl\Contracts\Repository\EggRepositoryInterface; -use Pterodactyl\Contracts\Repository\UserRepositoryInterface; -use Pterodactyl\Contracts\Repository\ServerRepositoryInterface; +use Pterodactyl\Repositories\Eloquent\ServerVariableRepository; use Pterodactyl\Services\Deployment\AllocationSelectionService; -use Pterodactyl\Contracts\Repository\AllocationRepositoryInterface; +use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException; use Pterodactyl\Services\Servers\ServerConfigurationStructureService; -use Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface; -use Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface as DaemonServerRepositoryInterface; /** * @preserveGlobalState disabled @@ -32,60 +35,60 @@ class ServerCreationServiceTest extends TestCase use MocksRequestException, MocksUuids; /** - * @var \Pterodactyl\Contracts\Repository\AllocationRepositoryInterface|\Mockery\Mock + * @var \Mockery\MockInterface */ private $allocationRepository; /** - * @var \Pterodactyl\Services\Deployment\AllocationSelectionService|\Mockery\Mock + * @var \Mockery\MockInterface */ private $allocationSelectionService; /** - * @var \Pterodactyl\Services\Servers\ServerConfigurationStructureService|\Mockery\Mock + * @var \Mockery\MockInterface */ private $configurationStructureService; /** - * @var \Illuminate\Database\ConnectionInterface|\Mockery\Mock + * @var \Mockery\MockInterface */ private $connection; /** - * @var \Pterodactyl\Contracts\Repository\Daemon\ServerRepositoryInterface|\Mockery\Mock + * @var \Mockery\MockInterface */ private $daemonServerRepository; /** - * @var \Pterodactyl\Contracts\Repository\EggRepositoryInterface|\Mockery\Mock + * @var \Mockery\MockInterface */ private $eggRepository; /** - * @var \Pterodactyl\Services\Deployment\FindViableNodesService|\Mockery\Mock + * @var \Mockery\MockInterface */ private $findViableNodesService; /** - * @var \Pterodactyl\Contracts\Repository\ServerRepositoryInterface|\Mockery\Mock + * @var \Mockery\MockInterface */ private $repository; /** - * @var \Pterodactyl\Contracts\Repository\ServerVariableRepositoryInterface|\Mockery\Mock + * @var \Mockery\MockInterface */ private $serverVariableRepository; /** - * @var \Pterodactyl\Contracts\Repository\UserRepositoryInterface|\Mockery\Mock - */ - private $userRepository; - - /** - * @var \Pterodactyl\Services\Servers\VariableValidatorService|\Mockery\Mock + * @var \Mockery\MockInterface */ private $validatorService; + /** + * @var \Mockery\MockInterface + */ + private $serverDeletionService; + /** * Setup tests. */ @@ -93,17 +96,17 @@ class ServerCreationServiceTest extends TestCase { parent::setUp(); - $this->allocationRepository = m::mock(AllocationRepositoryInterface::class); + $this->allocationRepository = m::mock(AllocationRepository::class); $this->allocationSelectionService = m::mock(AllocationSelectionService::class); $this->configurationStructureService = m::mock(ServerConfigurationStructureService::class); $this->connection = m::mock(ConnectionInterface::class); - $this->daemonServerRepository = m::mock(DaemonServerRepositoryInterface::class); - $this->eggRepository = m::mock(EggRepositoryInterface::class); $this->findViableNodesService = m::mock(FindViableNodesService::class); - $this->repository = m::mock(ServerRepositoryInterface::class); - $this->serverVariableRepository = m::mock(ServerVariableRepositoryInterface::class); - $this->userRepository = m::mock(UserRepositoryInterface::class); $this->validatorService = m::mock(VariableValidatorService::class); + $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); } /** @@ -148,7 +151,7 @@ class ServerCreationServiceTest extends TestCase $this->configurationStructureService->shouldReceive('handle')->with($model)->once()->andReturn(['test' => 'struct']); $this->daemonServerRepository->shouldReceive('setServer')->with($model)->once()->andReturnSelf(); - $this->daemonServerRepository->shouldReceive('create')->with(['test' => 'struct'], ['start_on_completion' => false])->once(); + $this->daemonServerRepository->shouldReceive('create')->with(['test' => 'struct'])->once(); $this->connection->shouldReceive('commit')->withNoArgs()->once()->andReturnNull(); $response = $this->getService()->handle($model->toArray()); @@ -250,12 +253,10 @@ class ServerCreationServiceTest extends TestCase /** * Test handling of node timeout or other daemon error. - * - * @expectedException \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException */ public function testExceptionShouldBeThrownIfTheRequestFails() { - $this->configureExceptionMock(); + $this->expectException(DaemonConnectionException::class); $model = factory(Server::class)->make([ 'uuid' => $this->getKnownUuid(), @@ -269,8 +270,16 @@ class ServerCreationServiceTest extends TestCase $this->validatorService->shouldReceive('handle')->once()->andReturn(collect([])); $this->configurationStructureService->shouldReceive('handle')->once()->andReturn([]); - $this->daemonServerRepository->shouldReceive('setServer')->with($model)->once()->andThrow($this->getExceptionMock()); - $this->connection->shouldReceive('rollBack')->withNoArgs()->once()->andReturnNull(); + $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); $this->getService()->handle($model->toArray()); } @@ -290,6 +299,7 @@ class ServerCreationServiceTest extends TestCase $this->eggRepository, $this->findViableNodesService, $this->configurationStructureService, + $this->serverDeletionService, $this->repository, $this->serverVariableRepository, $this->validatorService