Merge branch 'develop' into v2
This commit is contained in:
commit
d167ef1f89
8 changed files with 74 additions and 91 deletions
17
CHANGELOG.md
17
CHANGELOG.md
|
@ -3,6 +3,23 @@ This file is a running track of new features and fixes to each version of the pa
|
||||||
|
|
||||||
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
This project follows [Semantic Versioning](http://semver.org) guidelines.
|
||||||
|
|
||||||
|
## v1.6.0
|
||||||
|
### Fixed
|
||||||
|
* Fixes array merging logic for server transfers that would cause a 500 error to occur in some scenarios.
|
||||||
|
* Fixes user password updates not correctly logging the user out and returning a failure message even upon successful update.
|
||||||
|
* Fixes the count of used backups when browsing a paginated backup list for a server.
|
||||||
|
|
||||||
|
### Added
|
||||||
|
* Adds foreign key relationship on the `mount_node`, `mount_server` and `egg_mount` tables.
|
||||||
|
* Adds environment variable `PER_SCHEDULE_TASK_LIMIT` to allow manual overrides for the number of tasks that can exist on a single schedule. This is currently defaulted to `10`.
|
||||||
|
* OOM killer can now be configured at the time of server creation.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
* Server updates are not dependent on a successful call to Wings occurring — if the API call fails internally the error will be logged but the server update will still be persisted.
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
* Removed `WingsServerRepository::update()` function — if you were previously using this to modify server elements on Wings please replace calls to it with `::sync()` after updating Wings.
|
||||||
|
|
||||||
## v1.5.1
|
## v1.5.1
|
||||||
### Fixed
|
### Fixed
|
||||||
* Fixes Docker image 404ing instead of being able to access the Panel.
|
* Fixes Docker image 404ing instead of being able to access the Panel.
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
|
namespace Pterodactyl\Http\Controllers\Api\Remote\Servers;
|
||||||
|
|
||||||
use Carbon\CarbonImmutable;
|
use Carbon\CarbonImmutable;
|
||||||
use Illuminate\Support\Arr;
|
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Http\Response;
|
use Illuminate\Http\Response;
|
||||||
use Pterodactyl\Models\Allocation;
|
use Pterodactyl\Models\Allocation;
|
||||||
|
@ -61,20 +60,7 @@ class ServerTransferController extends Controller
|
||||||
return $this->processFailedTransfer($server->transfer);
|
return $this->processFailedTransfer($server->transfer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// We want to generate a new configuration using the new node_id value from the
|
$this->connection->transaction(function () use ($server) {
|
||||||
// transfer, and not the old node value.
|
|
||||||
$data = $this->configurationStructureService->handle($server, [
|
|
||||||
'node_id' => $server->transfer->new_node,
|
|
||||||
]);
|
|
||||||
|
|
||||||
$allocations = $server->getAllocationMappings();
|
|
||||||
$primary = array_key_first($allocations);
|
|
||||||
Arr::set($data, 'allocations.default.ip', $primary);
|
|
||||||
Arr::set($data, 'allocations.default.port', $allocations[$primary][0]);
|
|
||||||
Arr::set($data, 'service.skip_scripts', true);
|
|
||||||
Arr::set($data, 'suspended', false);
|
|
||||||
|
|
||||||
$this->connection->transaction(function () use ($data, $server) {
|
|
||||||
// This token is used by the new node the server is being transferred to. It allows
|
// This token is used by the new node the server is being transferred to. It allows
|
||||||
// that node to communicate with the old node during the process to initiate the
|
// that node to communicate with the old node during the process to initiate the
|
||||||
// actual file transfer.
|
// actual file transfer.
|
||||||
|
@ -93,7 +79,7 @@ class ServerTransferController extends Controller
|
||||||
$this->daemonTransferRepository
|
$this->daemonTransferRepository
|
||||||
->setServer($server)
|
->setServer($server)
|
||||||
->setNode($server->transfer->newNode)
|
->setNode($server->transfer->newNode)
|
||||||
->notify($server, $data, $server->node, $token->toString());
|
->notify($server, $token);
|
||||||
});
|
});
|
||||||
|
|
||||||
return new Response('', Response::HTTP_NO_CONTENT);
|
return new Response('', Response::HTTP_NO_CONTENT);
|
||||||
|
|
|
@ -4,6 +4,7 @@ namespace Pterodactyl\Repositories\Wings;
|
||||||
|
|
||||||
use Webmozart\Assert\Assert;
|
use Webmozart\Assert\Assert;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use GuzzleHttp\Exception\TransferException;
|
use GuzzleHttp\Exception\TransferException;
|
||||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
||||||
|
|
||||||
|
@ -34,34 +35,34 @@ class DaemonServerRepository extends DaemonRepository
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||||
*/
|
*/
|
||||||
public function create(array $data): void
|
public function create(bool $startOnCompletion = true): void
|
||||||
{
|
{
|
||||||
Assert::isInstanceOf($this->server, Server::class);
|
Assert::isInstanceOf($this->server, Server::class);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->getHttpClient()->post(
|
$this->getHttpClient()->post('/api/servers', [
|
||||||
'/api/servers',
|
'json' => [
|
||||||
[
|
'uuid' => $this->server->uuid,
|
||||||
'json' => $data,
|
'start_on_completion' => $startOnCompletion,
|
||||||
]
|
],
|
||||||
);
|
]);
|
||||||
} catch (TransferException $exception) {
|
} catch (GuzzleException $exception) {
|
||||||
throw new DaemonConnectionException($exception);
|
throw new DaemonConnectionException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Updates details about a server on the Daemon.
|
* Triggers a server sync on Wings.
|
||||||
*
|
*
|
||||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||||
*/
|
*/
|
||||||
public function update(array $data): void
|
public function sync(): void
|
||||||
{
|
{
|
||||||
Assert::isInstanceOf($this->server, Server::class);
|
Assert::isInstanceOf($this->server, Server::class);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->getHttpClient()->patch('/api/servers/' . $this->server->uuid, ['json' => $data]);
|
$this->getHttpClient()->post("/api/servers/{$this->server->uuid}/sync");
|
||||||
} catch (TransferException $exception) {
|
} catch (GuzzleException $exception) {
|
||||||
throw new DaemonConnectionException($exception);
|
throw new DaemonConnectionException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -101,26 +102,6 @@ class DaemonServerRepository extends DaemonRepository
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* By default this function will suspend a server instance on the daemon. However, passing
|
|
||||||
* "true" as the first argument will unsuspend the server.
|
|
||||||
*
|
|
||||||
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
|
||||||
*/
|
|
||||||
public function suspend(bool $unsuspend = false): void
|
|
||||||
{
|
|
||||||
Assert::isInstanceOf($this->server, Server::class);
|
|
||||||
|
|
||||||
try {
|
|
||||||
$this->getHttpClient()->patch(
|
|
||||||
'/api/servers/' . $this->server->uuid,
|
|
||||||
['json' => ['suspended' => !$unsuspend]]
|
|
||||||
);
|
|
||||||
} catch (TransferException $exception) {
|
|
||||||
throw new DaemonConnectionException($exception);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Requests the daemon to create a full archive of the server. Once the daemon is finished
|
* Requests the daemon to create a full archive of the server. Once the daemon is finished
|
||||||
* they will send a POST request to "/api/remote/servers/{uuid}/archive" with a boolean.
|
* they will send a POST request to "/api/remote/servers/{uuid}/archive" with a boolean.
|
||||||
|
|
|
@ -2,28 +2,31 @@
|
||||||
|
|
||||||
namespace Pterodactyl\Repositories\Wings;
|
namespace Pterodactyl\Repositories\Wings;
|
||||||
|
|
||||||
use Pterodactyl\Models\Node;
|
use Lcobucci\JWT\Token\Plain;
|
||||||
use Pterodactyl\Models\Server;
|
use Pterodactyl\Models\Server;
|
||||||
use GuzzleHttp\Exception\TransferException;
|
use GuzzleHttp\Exception\GuzzleException;
|
||||||
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
use Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException;
|
||||||
|
|
||||||
class DaemonTransferRepository extends DaemonRepository
|
class DaemonTransferRepository extends DaemonRepository
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @throws DaemonConnectionException
|
* @throws \Pterodactyl\Exceptions\Http\Connection\DaemonConnectionException
|
||||||
*/
|
*/
|
||||||
public function notify(Server $server, array $data, Node $node, string $token): void
|
public function notify(Server $server, Plain $token): void
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
$this->getHttpClient()->post('/api/transfer', [
|
$this->getHttpClient()->post('/api/transfer', [
|
||||||
'json' => [
|
'json' => [
|
||||||
'server_id' => $server->uuid,
|
'server_id' => $server->uuid,
|
||||||
'url' => $node->getConnectionAddress() . sprintf('/api/servers/%s/archive', $server->uuid),
|
'url' => $server->node->getConnectionAddress() . sprintf('/api/servers/%s/archive', $server->uuid),
|
||||||
'token' => 'Bearer ' . $token,
|
'token' => 'Bearer ' . $token->toString(),
|
||||||
'server' => $data,
|
'server' => [
|
||||||
|
'uuid' => $server->uuid,
|
||||||
|
'start_on_completion' => false,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
]);
|
]);
|
||||||
} catch (TransferException $exception) {
|
} catch (GuzzleException $exception) {
|
||||||
throw new DaemonConnectionException($exception);
|
throw new DaemonConnectionException($exception);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,8 @@ class BuildModificationService
|
||||||
* BuildModificationService constructor.
|
* BuildModificationService constructor.
|
||||||
*
|
*
|
||||||
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $structureService
|
* @param \Pterodactyl\Services\Servers\ServerConfigurationStructureService $structureService
|
||||||
|
* @param \Illuminate\Database\ConnectionInterface $connection
|
||||||
|
* @param \Pterodactyl\Repositories\Wings\DaemonServerRepository $daemonServerRepository
|
||||||
*/
|
*/
|
||||||
public function __construct(
|
public function __construct(
|
||||||
ServerConfigurationStructureService $structureService,
|
ServerConfigurationStructureService $structureService,
|
||||||
|
@ -56,46 +58,45 @@ class BuildModificationService
|
||||||
{
|
{
|
||||||
$this->connection->beginTransaction();
|
$this->connection->beginTransaction();
|
||||||
|
|
||||||
$this->processAllocations($server, $data);
|
/** @var \Pterodactyl\Models\Server $server */
|
||||||
|
$server = $this->connection->transaction(function() use ($server, $data) {
|
||||||
|
$this->processAllocations($server, $data);
|
||||||
|
|
||||||
if (isset($data['allocation_id']) && $data['allocation_id'] != $server->allocation_id) {
|
if (isset($data['allocation_id']) && $data['allocation_id'] != $server->allocation_id) {
|
||||||
try {
|
try {
|
||||||
Allocation::query()->where('id', $data['allocation_id'])->where('server_id', $server->id)->firstOrFail();
|
Allocation::query()->where('id', $data['allocation_id'])->where('server_id', $server->id)->firstOrFail();
|
||||||
} catch (ModelNotFoundException $ex) {
|
} catch (ModelNotFoundException $ex) {
|
||||||
throw new DisplayException('The requested default allocation is not currently assigned to this server.');
|
throw new DisplayException('The requested default allocation is not currently assigned to this server.');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// If any of these values are passed through in the data array go ahead and set
|
// If any of these values are passed through in the data array go ahead and set
|
||||||
// them correctly on the server model.
|
// them correctly on the server model.
|
||||||
$merge = Arr::only($data, ['oom_disabled', 'memory', 'swap', 'io', 'cpu', 'threads', 'disk', 'allocation_id']);
|
$merge = Arr::only($data, ['oom_disabled', 'memory', 'swap', 'io', 'cpu', 'threads', 'disk', 'allocation_id']);
|
||||||
|
|
||||||
$server->forceFill(array_merge($merge, [
|
$server->forceFill(array_merge($merge, [
|
||||||
'database_limit' => Arr::get($data, 'database_limit', 0) ?? null,
|
'database_limit' => Arr::get($data, 'database_limit', 0) ?? null,
|
||||||
'allocation_limit' => Arr::get($data, 'allocation_limit', 0) ?? null,
|
'allocation_limit' => Arr::get($data, 'allocation_limit', 0) ?? null,
|
||||||
'backup_limit' => Arr::get($data, 'backup_limit', 0) ?? 0,
|
'backup_limit' => Arr::get($data, 'backup_limit', 0) ?? 0,
|
||||||
]))->saveOrFail();
|
]))->saveOrFail();
|
||||||
|
|
||||||
$server = $server->fresh();
|
return $server->refresh();
|
||||||
|
});
|
||||||
|
|
||||||
$updateData = $this->structureService->handle($server);
|
$updateData = $this->structureService->handle($server);
|
||||||
|
|
||||||
// Because Wings always fetches an updated configuration from the Panel when booting
|
// Because Wings always fetches an updated configuration from the Panel when booting
|
||||||
// a server this type of exception can be safely "ignored" and just written to the logs.
|
// a server this type of exception can be safely "ignored" and just written to the logs.
|
||||||
// Ideally this request succeedes so we can apply resource modifications on the fly
|
// Ideally this request succeedes so we can apply resource modifications on the fly, but
|
||||||
// but if it fails it isn't the end of the world.
|
// if it fails we can just continue on as normal.
|
||||||
if (!empty($updateData['build'])) {
|
if (!empty($updateData['build'])) {
|
||||||
try {
|
try {
|
||||||
$this->daemonServerRepository->setServer($server)->update([
|
$this->daemonServerRepository->setServer($server)->sync();
|
||||||
'build' => $updateData['build'],
|
|
||||||
]);
|
|
||||||
} catch (DaemonConnectionException $exception) {
|
} catch (DaemonConnectionException $exception) {
|
||||||
Log::warning($exception, ['server_id' => $server->id]);
|
Log::warning($exception, ['server_id' => $server->id]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->connection->commit();
|
|
||||||
|
|
||||||
return $server;
|
return $server;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,15 +162,10 @@ class ServerCreationService
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$this->daemonServerRepository->setServer($server)->create(
|
$this->daemonServerRepository->setServer($server)->create(
|
||||||
array_merge(
|
Arr::get($data, 'start_on_completion', false) ?? false
|
||||||
$this->configurationStructureService->handle($server),
|
|
||||||
[
|
|
||||||
'start_on_completion' => Arr::get($data, 'start_on_completion', false),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} catch (DaemonConnectionException $exception) {
|
} catch (DaemonConnectionException $exception) {
|
||||||
$this->serverDeletionService->withForce(true)->handle($server);
|
$this->serverDeletionService->withForce()->handle($server);
|
||||||
|
|
||||||
throw $exception;
|
throw $exception;
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,9 +63,9 @@ class SuspensionService
|
||||||
'status' => $isSuspending ? Server::STATUS_SUSPENDED : null,
|
'status' => $isSuspending ? Server::STATUS_SUSPENDED : null,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
// Only send the suspension request to wings if the server is not currently being transferred.
|
// Only trigger a Wings server sync if it is not currently being transferred.
|
||||||
if (is_null($server->transfer)) {
|
if (is_null($server->transfer)) {
|
||||||
$this->daemonServerRepository->setServer($server)->suspend($action === self::ACTION_UNSUSPEND);
|
$this->daemonServerRepository->setServer($server)->sync();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,9 +75,9 @@ const JavaVersionModalFeature = () => {
|
||||||
return (
|
return (
|
||||||
<Modal visible={visible} onDismissed={() => setVisible(false)} closeOnBackground={false} showSpinnerOverlay={loading}>
|
<Modal visible={visible} onDismissed={() => setVisible(false)} closeOnBackground={false} showSpinnerOverlay={loading}>
|
||||||
<FlashMessageRender key={'feature:javaVersion'} css={tw`mb-4`}/>
|
<FlashMessageRender key={'feature:javaVersion'} css={tw`mb-4`}/>
|
||||||
<h2 css={tw`text-2xl mb-4 text-neutral-100`}>Invalid Java Version, Update Docker Image?</h2>
|
<h2 css={tw`text-2xl mb-4 text-neutral-100`}>Invalid Java version, update Docker image?</h2>
|
||||||
<p css={tw`mt-4`}>This server is unable to start due to the required java version not being met.</p>
|
<p css={tw`mt-4`}>This server is unable to start due to the required Java version not being met.</p>
|
||||||
<p css={tw`mt-4`}>By pressing {'"Update Docker Image"'} below you are acknowledging that the docker image this server uses will be changed to a image below that has the Java version you are requesting.</p>
|
<p css={tw`mt-4`}>By pressing {'"Update Docker Image"'} below you are acknowledging that the Docker image this server uses will be changed to an image below that has the Java version you are requesting.</p>
|
||||||
<div css={tw`sm:flex items-center mt-4`}>
|
<div css={tw`sm:flex items-center mt-4`}>
|
||||||
<p>Please select a Java version from the list below.</p>
|
<p>Please select a Java version from the list below.</p>
|
||||||
<Select
|
<Select
|
||||||
|
|
Loading…
Reference in a new issue