mirror of
https://github.com/pelican-dev/panel.git
synced 2025-09-08 23:08:37 +02:00
add backend for supporting multiple egg startup commands
This commit is contained in:
parent
8f277aaca0
commit
a4bc001728
@ -20,8 +20,7 @@ use Illuminate\Support\Str;
|
||||
* @property string $name
|
||||
* @property string|null $description
|
||||
* @property string[]|null $features
|
||||
* @property string $docker_image -- deprecated, use $docker_images
|
||||
* @property array<array-key, string> $docker_images
|
||||
* @property array<string, string> $docker_images
|
||||
* @property string|null $update_url
|
||||
* @property bool $force_outgoing_ip
|
||||
* @property string[]|null $file_denylist
|
||||
@ -30,7 +29,7 @@ use Illuminate\Support\Str;
|
||||
* @property string|null $config_logs
|
||||
* @property string|null $config_stop
|
||||
* @property int|null $config_from
|
||||
* @property string|null $startup
|
||||
* @property array<string, string> $startup_commands
|
||||
* @property bool $script_is_privileged
|
||||
* @property string|null $script_install
|
||||
* @property string $script_entry
|
||||
@ -69,7 +68,7 @@ class Egg extends Model implements Validatable
|
||||
/**
|
||||
* Defines the current egg export version.
|
||||
*/
|
||||
public const EXPORT_VERSION = 'PLCN_v2';
|
||||
public const EXPORT_VERSION = 'PLCN_v3';
|
||||
|
||||
/**
|
||||
* Fields that are not mass assignable.
|
||||
@ -88,7 +87,7 @@ class Egg extends Model implements Validatable
|
||||
'config_logs',
|
||||
'config_stop',
|
||||
'config_from',
|
||||
'startup',
|
||||
'startup_commands',
|
||||
'update_url',
|
||||
'script_is_privileged',
|
||||
'script_install',
|
||||
@ -109,7 +108,8 @@ class Egg extends Model implements Validatable
|
||||
'file_denylist.*' => ['string'],
|
||||
'docker_images' => ['required', 'array', 'min:1'],
|
||||
'docker_images.*' => ['required', 'string'],
|
||||
'startup' => ['required', 'nullable', 'string'],
|
||||
'startup_commands' => ['required', 'array', 'min:1'],
|
||||
'startup_commands.*' => ['required', 'string'],
|
||||
'config_from' => ['sometimes', 'bail', 'nullable', 'numeric', 'exists:eggs,id'],
|
||||
'config_stop' => ['required_without:config_from', 'nullable', 'string', 'max:255'],
|
||||
'config_startup' => ['required_without:config_from', 'nullable', 'json'],
|
||||
@ -141,6 +141,7 @@ class Egg extends Model implements Validatable
|
||||
'features' => 'array',
|
||||
'docker_images' => 'array',
|
||||
'file_denylist' => 'array',
|
||||
'startup_commands' => 'array',
|
||||
'tags' => 'array',
|
||||
];
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ namespace App\Services\Eggs;
|
||||
use App\Models\Egg;
|
||||
use App\Models\Server;
|
||||
use App\Models\ServerVariable;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class EggChangerService
|
||||
{
|
||||
@ -21,8 +22,8 @@ class EggChangerService
|
||||
// Change egg id, default image and startup command
|
||||
$server->forceFill([
|
||||
'egg_id' => $newEgg->id,
|
||||
'image' => array_values($newEgg->docker_images)[0],
|
||||
'startup' => $newEgg->startup,
|
||||
'image' => Arr::first($newEgg->docker_images),
|
||||
'startup' => Arr::first($newEgg->startup_commands),
|
||||
])->saveOrFail();
|
||||
|
||||
$oldVariables = [];
|
||||
|
@ -33,7 +33,7 @@ class EggExporterService
|
||||
'features' => $egg->features,
|
||||
'docker_images' => $egg->docker_images,
|
||||
'file_denylist' => Collection::make($egg->inherit_file_denylist)->filter(fn ($v) => !empty($v))->values(),
|
||||
'startup' => $egg->startup,
|
||||
'startup_commands' => $egg->startup_commands,
|
||||
'config' => [
|
||||
'files' => $egg->inherit_config_files,
|
||||
'startup' => $egg->inherit_config_startup,
|
||||
|
@ -133,8 +133,9 @@ class EggImporterService
|
||||
$version = $parsed['meta']['version'] ?? '';
|
||||
|
||||
$parsed = match ($version) {
|
||||
'PTDL_v1' => $this->convertToV2($parsed),
|
||||
'PTDL_v2', 'PLCN_v1', 'PLCN_v2' => $parsed,
|
||||
'PTDL_v1' => $this->convertToV3($this->convertLegacy($parsed)),
|
||||
'PTDL_v2', 'PLCN_v1', 'PLCN_v2' => $this->convertToV3($parsed),
|
||||
'PLCN_v3' => $parsed,
|
||||
default => throw new InvalidFileUploadException('The file format is not recognized.'),
|
||||
};
|
||||
|
||||
@ -180,7 +181,7 @@ class EggImporterService
|
||||
if ($forbidden->count()) {
|
||||
$parsed['variables'] = $allowed->merge($updatedVariables)->all();
|
||||
|
||||
if (!empty($parsed['startup'])) {
|
||||
if (count($parsed['startup_commands']) > 0) {
|
||||
$pattern = '/\b(' . collect($forbidden)->map(fn ($variable) => preg_quote($variable['env_variable']))->join('|') . ')\b/';
|
||||
$parsed['startup'] = preg_replace($pattern, 'SERVER_$1', $parsed['startup']) ?? $parsed['startup'];
|
||||
}
|
||||
@ -206,7 +207,7 @@ class EggImporterService
|
||||
'config_startup' => json_encode(json_decode(Arr::get($parsed, 'config.startup')), JSON_PRETTY_PRINT),
|
||||
'config_logs' => json_encode(json_decode(Arr::get($parsed, 'config.logs')), JSON_PRETTY_PRINT),
|
||||
'config_stop' => Arr::get($parsed, 'config.stop'),
|
||||
'startup' => Arr::get($parsed, 'startup'),
|
||||
'startup_commands' => Arr::get($parsed, 'startup_commands'),
|
||||
'script_install' => Arr::get($parsed, 'scripts.installation.script'),
|
||||
'script_entry' => Arr::get($parsed, 'scripts.installation.entrypoint'),
|
||||
'script_container' => Arr::get($parsed, 'scripts.installation.container'),
|
||||
@ -217,7 +218,7 @@ class EggImporterService
|
||||
* @param array<string, mixed> $parsed
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function convertToV2(array $parsed): array
|
||||
protected function convertLegacy(array $parsed): array
|
||||
{
|
||||
if (!isset($parsed['images'])) {
|
||||
$images = [Arr::get($parsed, 'image') ?? 'nil'];
|
||||
@ -234,4 +235,21 @@ class EggImporterService
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $parsed
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
protected function convertToV3(array $parsed): array
|
||||
{
|
||||
$startup = $parsed['startup'];
|
||||
|
||||
unset($parsed['startup']);
|
||||
|
||||
$parsed['startup_commands'] = [
|
||||
$startup => $startup,
|
||||
];
|
||||
|
||||
return $parsed;
|
||||
}
|
||||
}
|
||||
|
@ -56,8 +56,8 @@ class ServerCreationService
|
||||
$egg = Egg::query()->findOrFail($data['egg_id']);
|
||||
|
||||
// Fill missing fields from egg
|
||||
$data['image'] ??= collect($egg->docker_images)->first();
|
||||
$data['startup'] ??= $egg->startup;
|
||||
$data['image'] ??= Arr::first($egg->docker_images);
|
||||
$data['startup'] ??= Arr::first($egg->startup_commands);
|
||||
|
||||
// If a deployment object has been passed we need to get the allocation and node that the server should use.
|
||||
if ($deployment) {
|
||||
|
@ -84,8 +84,8 @@ class StartupModificationService
|
||||
]);
|
||||
|
||||
// Fill missing fields from egg
|
||||
$data['docker_image'] = $data['docker_image'] ?? collect($egg->docker_images)->first();
|
||||
$data['startup'] = $data['startup'] ?? $egg->startup;
|
||||
$data['docker_image'] ??= Arr::first($egg->docker_images);
|
||||
$data['startup'] ??= Arr::first($egg->startup_commands);
|
||||
}
|
||||
|
||||
$server->fill([
|
||||
|
@ -48,10 +48,7 @@ class EggTransformer extends BaseTransformer
|
||||
'description' => $model->description,
|
||||
'features' => $model->features,
|
||||
'tags' => $model->tags,
|
||||
// "docker_image" is deprecated, but left here to avoid breaking too many things at once
|
||||
// in external software. We'll remove it down the road once things have gotten the chance
|
||||
// to upgrade to using "docker_images".
|
||||
'docker_image' => count($model->docker_images) > 0 ? Arr::first($model->docker_images) : '',
|
||||
'docker_image' => Arr::first($model->docker_images, default: ''), // docker_images, use startup_commands
|
||||
'docker_images' => $model->docker_images,
|
||||
'config' => [
|
||||
'files' => $files,
|
||||
@ -61,7 +58,8 @@ class EggTransformer extends BaseTransformer
|
||||
'file_denylist' => $model->inherit_file_denylist,
|
||||
'extends' => $model->config_from,
|
||||
],
|
||||
'startup' => $model->startup,
|
||||
'startup' => Arr::first($model->startup_commands, default: ''), // deprecated, use startup_commands
|
||||
'startup_commands' => $model->startup_commands,
|
||||
'script' => [
|
||||
'privileged' => $model->script_is_privileged,
|
||||
'install' => $model->copy_script_install,
|
||||
|
@ -30,7 +30,7 @@ class EggFactory extends Factory
|
||||
'config_files' => '{}',
|
||||
'name' => $this->faker->name(),
|
||||
'description' => implode(' ', $this->faker->sentences()),
|
||||
'startup' => 'java -jar test.jar',
|
||||
'startup_commands' => ['java -jar test.jar'],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('eggs', function (Blueprint $table) {
|
||||
$table->json('startup_commands')->after('startup')->nullable();
|
||||
});
|
||||
|
||||
DB::table('eggs')->select(['id', 'startup'])->cursor()->each(function ($egg) {
|
||||
$startup = $egg->startup;
|
||||
|
||||
DB::table('eggs')->where('id', $egg->id)->update(['startup_commands' => [$startup => $startup]]);
|
||||
});
|
||||
|
||||
Schema::table('eggs', function (Blueprint $table) {
|
||||
$table->dropColumn('startup');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('eggs', function (Blueprint $table) {
|
||||
$table->text('startup')->after('startup_commands');
|
||||
});
|
||||
|
||||
DB::table('eggs')->select(['id', 'startup_commands'])->cursor()->each(function ($egg) {
|
||||
DB::table('eggs')->where('id', $egg->id)->update([
|
||||
'startup' => Arr::first(json_decode($egg->startup_commands, true, 512, JSON_THROW_ON_ERROR)),
|
||||
]);
|
||||
});
|
||||
|
||||
Schema::table('eggs', function (Blueprint $table) {
|
||||
$table->dropColumn('startup_commands');
|
||||
});
|
||||
}
|
||||
};
|
Loading…
x
Reference in New Issue
Block a user