Remove suspended & installing fields, replace with single status field

This commit is contained in:
Dane Everitt 2021-01-17 15:51:56 -08:00
parent 4c29be2e54
commit a75a347d65
No known key found for this signature in database
GPG key ID: EEA66103B3D71F53
24 changed files with 115 additions and 59 deletions

View file

@ -207,7 +207,7 @@ class ServerViewController extends Controller
*/
public function manage(Request $request, Server $server)
{
if ($server->installed > 1) {
if ($server->status === Server::STATUS_INSTALL_FAILED) {
throw new DisplayException(
'This server is in a failed install state and cannot be recovered. Please delete and re-create the server.'
);

View file

@ -228,12 +228,12 @@ class ServersController extends Controller
*/
public function toggleInstall(Server $server)
{
if ($server->installed > 1) {
if ($server->status === Server::STATUS_INSTALL_FAILED) {
throw new DisplayException(trans('admin/server.exceptions.marked_as_failed'));
}
$this->repository->update($server->id, [
'installed' => ! $server->installed,
'status' => $server->isInstalled() ? Server::STATUS_INSTALLING : null,
], true, true);
$this->alert->success(trans('admin/server.alerts.install_toggled'))->flash();

View file

@ -118,10 +118,8 @@ class SftpAuthenticationController extends Controller
// Remember, for security purposes, only reveal the existence of the server to people that
// have provided valid credentials, and have permissions to know about it.
if ($server->installed !== 1 || $server->suspended) {
throw new BadRequestHttpException(
'Server is not installed or is currently suspended.'
);
if ($server->isSuspended() || !$server->isInstalled()) {
throw new BadRequestHttpException('Server is not installed or is currently suspended.');
}
return new JsonResponse([

View file

@ -29,7 +29,7 @@ class ServerInstalled
);
}
if ($server->installed !== 1) {
if (! $server->isInstalled()) {
throw new HttpException(
Response::HTTP_FORBIDDEN, 'Access to this resource is not allowed due to the current installation state.'
);

View file

@ -64,7 +64,7 @@ class AuthenticateServerAccess
}
}
if ($server->suspended && ! $request->routeIs('api:client:server.resources')) {
if ($server->isSuspended() && ! $request->routeIs('api:client:server.resources')) {
throw new BadRequestHttpException(
'This server is currently suspended and the functionality requested is unavailable.'
);

View file

@ -63,7 +63,7 @@ class AccessingValidServer
$isApiRequest = $request->expectsJson() || $request->is(...$this->config->get('pterodactyl.json_routes', []));
$server = $this->repository->getByUuid($attributes instanceof Server ? $attributes->uuid : $attributes);
if ($server->suspended) {
if ($server->isSuspended()) {
if ($isApiRequest) {
throw new AccessDeniedHttpException('Server is suspended and cannot be accessed.');
}
@ -73,7 +73,7 @@ class AccessingValidServer
// Servers can have install statuses other than 1 or 0, so don't check
// for a bool-type operator here.
if ($server->installed !== 1) {
if (! $server->isInstalled()) {
if ($isApiRequest) {
throw new ConflictHttpException('Server is still completing the installation process.');
}

View file

@ -15,8 +15,8 @@ use Znck\Eloquent\Traits\BelongsToThrough;
* @property int $node_id
* @property string $name
* @property string $description
* @property string|null $status
* @property bool $skip_scripts
* @property bool $suspended
* @property int $owner_id
* @property int $memory
* @property int $swap
@ -30,7 +30,6 @@ use Znck\Eloquent\Traits\BelongsToThrough;
* @property int $egg_id
* @property string $startup
* @property string $image
* @property int $installed
* @property int $allocation_limit
* @property int $database_limit
* @property int $backup_limit
@ -64,9 +63,9 @@ class Server extends Model
*/
const RESOURCE_NAME = 'server';
const STATUS_INSTALLING = 0;
const STATUS_INSTALLED = 1;
const STATUS_INSTALL_FAILED = 2;
const STATUS_INSTALLING = 'installing';
const STATUS_INSTALL_FAILED = 'install_failed';
const STATUS_SUSPENDED = 'suspended';
/**
* The table associated with the model.
@ -82,6 +81,7 @@ class Server extends Model
* @var array
*/
protected $attributes = [
'status' => self::STATUS_INSTALLING,
'oom_disabled' => true,
];
@ -104,7 +104,7 @@ class Server extends Model
*
* @var array
*/
protected $guarded = ['id', 'installed', self::CREATED_AT, self::UPDATED_AT, 'deleted_at'];
protected $guarded = ['id', self::CREATED_AT, self::UPDATED_AT, 'deleted_at'];
/**
* @var array
@ -115,6 +115,7 @@ class Server extends Model
'name' => 'required|string|min:1|max:191',
'node_id' => 'required|exists:nodes,id',
'description' => 'string',
'status' => 'nullable|string',
'memory' => 'required|numeric|min:0',
'swap' => 'required|numeric|min:-1',
'io' => 'required|numeric|between:10,1000',
@ -142,7 +143,6 @@ class Server extends Model
protected $casts = [
'node_id' => 'integer',
'skip_scripts' => 'boolean',
'suspended' => 'boolean',
'owner_id' => 'integer',
'memory' => 'integer',
'swap' => 'integer',
@ -153,7 +153,6 @@ class Server extends Model
'allocation_id' => 'integer',
'nest_id' => 'integer',
'egg_id' => 'integer',
'installed' => 'integer',
'database_limit' => 'integer',
'allocation_limit' => 'integer',
'backup_limit' => 'integer',
@ -176,7 +175,12 @@ class Server extends Model
*/
public function isInstalled(): bool
{
return $this->installed === 1;
return $this->status !== self::STATUS_INSTALLING && $this->status !== self::STATUS_INSTALL_FAILED;
}
public function isSuspended(): bool
{
return $this->status === self::STATUS_SUSPENDED;
}
/**

View file

@ -44,7 +44,7 @@ class ReinstallServerService
public function handle(Server $server)
{
return $this->connection->transaction(function () use ($server) {
$server->forceFill(['installed' => Server::STATUS_INSTALLING])->save();
$server->fill(['status' => Server::STATUS_INSTALLING])->save();
$this->daemonServerRepository->setServer($server)->reinstall();

View file

@ -60,7 +60,7 @@ class ServerConfigurationStructureService
{
return [
'uuid' => $server->uuid,
'suspended' => $server->suspended,
'suspended' => $server->isSuspended(),
'environment' => $this->environment->handle($server),
'invocation' => $server->startup,
'skip_egg_scripts' => $server->skip_scripts,
@ -137,7 +137,7 @@ class ServerConfigurationStructureService
'skip_scripts' => $server->skip_scripts,
],
'rebuild' => false,
'suspended' => (int)$server->suspended,
'suspended' => $server->isSuspended() ? 1 : 0,
];
}
}

View file

@ -229,8 +229,8 @@ class ServerCreationService
'node_id' => Arr::get($data, 'node_id'),
'name' => Arr::get($data, 'name'),
'description' => Arr::get($data, 'description') ?? '',
'status' => Server::STATUS_INSTALLING,
'skip_scripts' => Arr::get($data, 'skip_scripts') ?? isset($data['skip_scripts']),
'suspended' => false,
'owner_id' => Arr::get($data, 'owner_id'),
'memory' => Arr::get($data, 'memory'),
'swap' => Arr::get($data, 'swap'),

View file

@ -6,7 +6,6 @@ use Webmozart\Assert\Assert;
use Pterodactyl\Models\Server;
use Illuminate\Database\ConnectionInterface;
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
use Pterodactyl\Exceptions\Http\Server\ServerTransferringException;
class SuspensionService
@ -54,7 +53,7 @@ class SuspensionService
// Nothing needs to happen if we're suspending the server and it is already
// suspended in the database. Additionally, nothing needs to happen if the server
// is not suspended and we try to un-suspend the instance.
if ($isSuspending === $server->suspended) {
if ($isSuspending === $server->isSuspended()) {
return;
}
@ -63,9 +62,9 @@ class SuspensionService
throw new ServerTransferringException;
}
$this->connection->transaction(function () use ($action, $server) {
$this->connection->transaction(function () use ($action, $server, $isSuspending) {
$server->update([
'suspended' => $action === self::ACTION_SUSPEND,
'status' => $isSuspending ? Server::STATUS_SUSPENDED : null,
]);
// Only send the suspension request to wings if the server is not currently being transferred.

View file

@ -66,7 +66,7 @@ class ServerTransformer extends BaseTransformer
'identifier' => $server->uuidShort,
'name' => $server->name,
'description' => $server->description,
'suspended' => (bool) $server->suspended,
'suspended' => $server->isSuspended(),
'limits' => [
'memory' => $server->memory,
'swap' => $server->swap,
@ -88,7 +88,7 @@ class ServerTransformer extends BaseTransformer
'container' => [
'startup_command' => $server->startup,
'image' => $server->image,
'installed' => (int) $server->installed === 1,
'installed' => $server->isInstalled() ? 1 : 0,
'environment' => $this->environmentService->handle($server),
],
$server->getUpdatedAtColumn() => $this->formatTimestamp($server->updated_at),

View file

@ -70,8 +70,8 @@ class ServerTransformer extends BaseClientTransformer
'allocations' => $server->allocation_limit,
'backups' => $server->backup_limit,
],
'is_suspended' => $server->suspended,
'is_installing' => $server->installed !== 1,
'is_suspended' => $server->isSuspended(),
'is_installing' => ! $server->isInstalled(),
'is_transferring' => ! is_null($server->transfer),
];
}

View file

@ -27,14 +27,13 @@ $factory->define(Pterodactyl\Models\Server::class, function (Faker $faker) {
'name' => $faker->firstName,
'description' => implode(' ', $faker->sentences()),
'skip_scripts' => 0,
'suspended' => 0,
'status' => null,
'memory' => 512,
'swap' => 0,
'disk' => 512,
'io' => 500,
'cpu' => 0,
'oom_disabled' => 0,
'installed' => 1,
'database_limit' => null,
'allocation_limit' => null,
'created_at' => Carbon::now(),

View file

@ -0,0 +1,55 @@
<?php
use Illuminate\Support\Facades\DB;
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class AddGenericServerStatusColumn extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('servers', function (Blueprint $table) {
$table->string('status')->nullable()->after('description');
});
DB::transaction(function () {
DB::update('UPDATE servers SET `status` = \'suspended\' WHERE `suspended` = 1');
DB::update('UPDATE servers SET `status` = \'installing\' WHERE `installed` = 0');
DB::update('UPDATE servers SET `status` = \'install_failed\' WHERE `installed` = 2');
});
Schema::table('servers', function (Blueprint $table) {
$table->dropColumn('suspended');
$table->dropColumn('installed');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('servers', function (Blueprint $table) {
$table->unsignedTinyInteger('suspended')->default(0);
$table->unsignedTinyInteger('installed')->default(0);
});
DB::transaction(function () {
DB::update('UPDATE servers SET `suspended` = 1 WHERE `status` = \'suspended\'');
DB::update('UPDATE servers SET `installed` = 1 WHERE `status` IS NULL');
DB::update('UPDATE servers SET `installed` = 2 WHERE `status` = \'install_failed\'');
});
Schema::table('servers', function (Blueprint $table) {
$table->dropColumn('status');
});
}
}

View file

@ -57,9 +57,9 @@
<code>{{ $server->allocation->alias }}:{{ $server->allocation->port }}</code>
</td>
<td class="text-center">
@if($server->suspended)
@if($server->isSuspended())
<span class="label bg-maroon">Suspended</span>
@elseif(! $server->installed)
@elseif(! $server->isInstalled())
<span class="label label-warning">Installing</span>
@else
<span class="label label-success">Active</span>

View file

@ -8,7 +8,7 @@
<ul class="nav nav-tabs">
<li class="{{ $router->currentRouteNamed('admin.servers.view') ? 'active' : '' }}">
<a href="{{ route('admin.servers.view', $server->id) }}">About</a></li>
@if($server->installed === 1)
@if($server->isInstalled())
<li class="{{ $router->currentRouteNamed('admin.servers.view.details') ? 'active' : '' }}">
<a href="{{ route('admin.servers.view.details', $server->id) }}">Details</a>
</li>

View file

@ -133,7 +133,7 @@
<div class="box box-primary">
<div class="box-body" style="padding-bottom: 0px;">
<div class="row">
@if($server->suspended)
@if($server->isSuspended())
<div class="col-sm-12">
<div class="small-box bg-yellow">
<div class="inner">
@ -142,11 +142,11 @@
</div>
</div>
@endif
@if($server->installed !== 1)
@if(!$server->isInstalled())
<div class="col-sm-12">
<div class="small-box {{ (! $server->installed) ? 'bg-blue' : 'bg-maroon' }}">
<div class="small-box {{ (! $server->isInstalled()) ? 'bg-blue' : 'bg-maroon' }}">
<div class="inner">
<h3 class="no-margin">{{ (! $server->installed) ? 'Installing' : 'Install Failed' }}</h3>
<h3 class="no-margin">{{ (! $server->isInstalled()) ? 'Installing' : 'Install Failed' }}</h3>
</div>
</div>
</div>

View file

@ -31,7 +31,7 @@
<p>This will reinstall the server with the assigned service scripts. <strong>Danger!</strong> This could overwrite server data.</p>
</div>
<div class="box-footer">
@if($server->installed === 1)
@if($server->isInstalled())
<form action="{{ route('admin.servers.view.manage.reinstall', $server->id) }}" method="POST">
{!! csrf_field() !!}
<button type="submit" class="btn btn-danger">Reinstall Server</button>
@ -59,7 +59,7 @@
</div>
</div>
@if(! $server->suspended)
@if(! $server->isSuspended())
<div class="col-sm-4">
<div class="box box-warning">
<div class="box-header with-border">

View file

@ -73,7 +73,7 @@ class SettingsControllerTest extends ClientApiIntegrationTestCase
{
/** @var \Pterodactyl\Models\Server $server */
[$user, $server] = $this->generateTestAccount($permissions);
$this->assertSame(Server::STATUS_INSTALLED, $server->installed);
$this->assertTrue($server->isInstalled());
$service = Mockery::mock(DaemonServerRepository::class);
$this->app->instance(DaemonServerRepository::class, $service);
@ -91,7 +91,7 @@ class SettingsControllerTest extends ClientApiIntegrationTestCase
->assertStatus(Response::HTTP_ACCEPTED);
$server = $server->refresh();
$this->assertSame(Server::STATUS_INSTALLING, $server->installed);
$this->assertSame(Server::STATUS_INSTALLING, $server->status);
}
/**
@ -107,7 +107,7 @@ class SettingsControllerTest extends ClientApiIntegrationTestCase
->assertStatus(Response::HTTP_FORBIDDEN);
$server = $server->refresh();
$this->assertSame(Server::STATUS_INSTALLED, $server->installed);
$this->assertTrue($server->isInstalled());
}
/**

View file

@ -142,7 +142,7 @@ class ServerCreationServiceTest extends IntegrationTestCase
$this->assertSame($allocations[0]->id, $response->allocations[0]->id);
$this->assertSame($allocations[4]->id, $response->allocations[1]->id);
$this->assertFalse($response->suspended);
$this->assertFalse($response->isSuspended());
$this->assertTrue($response->oom_disabled);
$this->assertSame(0, $response->database_limit);
$this->assertSame(0, $response->allocation_limit);

View file

@ -98,7 +98,7 @@ class StartupModificationServiceTest extends IntegrationTestCase
$this->assertTrue($response->skip_scripts);
// Make sure we don't revert back to a lurking bug that causes servers to get marked
// as not installed when you modify the startup...
$this->assertSame(1, $response->installed);
$this->assertTrue($response->isInstalled());
}
/**

View file

@ -4,6 +4,7 @@ namespace Pterodactyl\Tests\Integration\Services\Servers;
use Mockery;
use InvalidArgumentException;
use Pterodactyl\Models\Server;
use Pterodactyl\Services\Servers\SuspensionService;
use Pterodactyl\Tests\Integration\IntegrationTestCase;
use Pterodactyl\Repositories\Wings\DaemonServerRepository;
@ -26,7 +27,7 @@ class SuspensionServiceTest extends IntegrationTestCase
public function testServerIsSuspendedAndUnsuspended()
{
$server = $this->createServerModel(['suspended' => false]);
$server = $this->createServerModel();
$this->repository->expects('setServer')->twice()->andReturnSelf();
$this->repository->expects('suspend')->with(false)->andReturnUndefined();
@ -34,30 +35,30 @@ class SuspensionServiceTest extends IntegrationTestCase
$this->getService()->toggle($server, SuspensionService::ACTION_SUSPEND);
$server->refresh();
$this->assertTrue($server->suspended);
$this->assertTrue($server->isSuspended());
$this->repository->expects('suspend')->with(true)->andReturnUndefined();
$this->getService()->toggle($server, SuspensionService::ACTION_UNSUSPEND);
$server->refresh();
$this->assertFalse($server->suspended);
$this->assertFalse($server->isSuspended());
}
public function testNoActionIsTakenIfSuspensionStatusIsUnchanged()
{
$server = $this->createServerModel(['suspended' => false]);
$server = $this->createServerModel();
$this->getService()->toggle($server, SuspensionService::ACTION_UNSUSPEND);
$server->refresh();
$this->assertFalse($server->suspended);
$this->assertFalse($server->isSuspended());
$server->update(['suspended' => true]);
$server->update(['status' => Server::STATUS_SUSPENDED]);
$this->getService()->toggle($server, SuspensionService::ACTION_SUSPEND);
$server->refresh();
$this->assertTrue($server->suspended);
$this->assertTrue($server->isSuspended());
}
public function testExceptionIsThrownIfInvalidActionsArePassed()

View file

@ -49,7 +49,7 @@ class AccessingValidServerTest extends MiddlewareTestCase
$this->expectException(AccessDeniedHttpException::class);
$this->expectExceptionMessage('Server is suspended and cannot be accessed.');
$model = factory(Server::class)->make(['suspended' => 1]);
$model = factory(Server::class)->make(['status' => Server::STATUS_SUSPENDED]);
$this->request->shouldReceive('route->parameter')->with('server')->once()->andReturn('123456');
$this->request->shouldReceive('expectsJson')->withNoArgs()->once()->andReturn(true);
@ -126,9 +126,9 @@ class AccessingValidServerTest extends MiddlewareTestCase
$this->refreshApplication();
return [
[factory(Server::class)->make(['suspended' => 1]), 'errors.suspended', 403],
[factory(Server::class)->make(['installed' => 0]), 'errors.installing', 409],
[factory(Server::class)->make(['installed' => 2]), 'errors.installing', 409],
[factory(Server::class)->make(['status' => Server::STATUS_SUSPENDED]), 'errors.suspended', 403],
[factory(Server::class)->make(['status' => Server::STATUS_INSTALLING]), 'errors.installing', 409],
[factory(Server::class)->make(['status' => Server::STATUS_INSTALL_FAILED]), 'errors.installing', 409],
];
}