Extract Ladill Servers as standalone app at servers.ladill.com.
VPS and dedicated server ordering, managed panels, SSO, billing, and launcher integration — forked from hosting infrastructure with server-focused routes and dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\Hosting\PanelRuntimes;
|
||||
|
||||
use App\Models\CustomerHostingOrder;
|
||||
use App\Models\ServerAgent;
|
||||
use App\Models\ServerTask;
|
||||
use App\Services\Hosting\ServerAgentBootstrapService;
|
||||
use Illuminate\Support\Str;
|
||||
use RuntimeException;
|
||||
|
||||
class ServerAgentPanelRuntime
|
||||
{
|
||||
public function __construct(
|
||||
private ServerAgentBootstrapService $bootstrap,
|
||||
) {}
|
||||
|
||||
public function label(): string
|
||||
{
|
||||
return 'Ladill Hosting Panel';
|
||||
}
|
||||
|
||||
public function supports(CustomerHostingOrder $order): bool
|
||||
{
|
||||
return (bool) data_get($order->meta, 'server_panel_runtime.managed_stack_candidate', false);
|
||||
}
|
||||
|
||||
public function ensureAgent(CustomerHostingOrder $order): ServerAgent
|
||||
{
|
||||
if (! $this->supports($order)) {
|
||||
throw new RuntimeException('This server image is not enabled for agent-backed Ladill hosting tasks.');
|
||||
}
|
||||
|
||||
return $this->bootstrap->ensureBootstrap($order)['agent'];
|
||||
}
|
||||
|
||||
public function queueDomainTask(CustomerHostingOrder $order, string $domain, ?string $documentRoot = null, ?string $phpVersion = null): ServerTask
|
||||
{
|
||||
return $this->queueTask($order, ServerTask::TYPE_DOMAIN_ADD, array_filter([
|
||||
'domain' => strtolower($domain),
|
||||
'document_root' => $documentRoot,
|
||||
'php_version' => $phpVersion,
|
||||
], static fn ($value): bool => $value !== null && $value !== ''));
|
||||
}
|
||||
|
||||
public function queueSslTask(CustomerHostingOrder $order, string $domain): ServerTask
|
||||
{
|
||||
return $this->queueTask($order, ServerTask::TYPE_SSL_REQUEST, [
|
||||
'domain' => strtolower($domain),
|
||||
]);
|
||||
}
|
||||
|
||||
public function queueDatabaseTask(CustomerHostingOrder $order, string $name): ServerTask
|
||||
{
|
||||
return $this->queueTask($order, ServerTask::TYPE_DATABASE_CREATE, [
|
||||
'name' => Str::lower($name),
|
||||
]);
|
||||
}
|
||||
|
||||
public function queueSiteDeleteTask(CustomerHostingOrder $order, string $domain): ServerTask
|
||||
{
|
||||
return $this->queueTask($order, ServerTask::TYPE_SITE_DELETE, [
|
||||
'domain' => strtolower($domain),
|
||||
]);
|
||||
}
|
||||
|
||||
public function queuePhpTask(CustomerHostingOrder $order, string $domain, string $phpVersion): ServerTask
|
||||
{
|
||||
return $this->queueTask($order, ServerTask::TYPE_PHP_CONFIGURE, [
|
||||
'domain' => strtolower($domain),
|
||||
'php_version' => $phpVersion,
|
||||
]);
|
||||
}
|
||||
|
||||
public function queueCronTask(
|
||||
CustomerHostingOrder $order,
|
||||
string $operation,
|
||||
?string $name = null,
|
||||
?string $expression = null,
|
||||
?string $command = null,
|
||||
?string $user = null,
|
||||
): ServerTask {
|
||||
$taskType = match ($operation) {
|
||||
'list' => ServerTask::TYPE_CRON_LIST,
|
||||
'upsert' => ServerTask::TYPE_CRON_UPSERT,
|
||||
'remove' => ServerTask::TYPE_CRON_REMOVE,
|
||||
default => throw new RuntimeException('Unsupported cron operation.'),
|
||||
};
|
||||
|
||||
return $this->queueTask($order, $taskType, array_filter([
|
||||
'name' => $name,
|
||||
'expression' => $expression,
|
||||
'command' => $command,
|
||||
'user' => $user,
|
||||
], static fn ($value): bool => $value !== null && $value !== ''));
|
||||
}
|
||||
|
||||
public function queueLogTask(CustomerHostingOrder $order, string $target, ?string $domain = null, int $lines = 120): ServerTask
|
||||
{
|
||||
return $this->queueTask($order, ServerTask::TYPE_LOG_READ, [
|
||||
'target' => $target,
|
||||
'domain' => $domain ? strtolower($domain) : null,
|
||||
'lines' => max(20, min(500, $lines)),
|
||||
]);
|
||||
}
|
||||
|
||||
public function queueFileTask(CustomerHostingOrder $order, string $operation, string $path, ?string $content = null): ServerTask
|
||||
{
|
||||
$taskType = match ($operation) {
|
||||
'list' => ServerTask::TYPE_FILE_LIST,
|
||||
'read' => ServerTask::TYPE_FILE_READ,
|
||||
'write' => ServerTask::TYPE_FILE_WRITE,
|
||||
default => throw new RuntimeException('Unsupported file operation.'),
|
||||
};
|
||||
|
||||
return $this->queueTask($order, $taskType, array_filter([
|
||||
'path' => $path,
|
||||
'content' => $content,
|
||||
], static fn ($value): bool => $value !== null));
|
||||
}
|
||||
|
||||
private function queueTask(CustomerHostingOrder $order, string $type, array $payload): ServerTask
|
||||
{
|
||||
$agent = $this->ensureAgent($order);
|
||||
|
||||
return ServerTask::create([
|
||||
'customer_hosting_order_id' => $order->id,
|
||||
'server_agent_id' => $agent->id,
|
||||
'type' => $type,
|
||||
'status' => ServerTask::STATUS_QUEUED,
|
||||
'payload' => $payload,
|
||||
'progress' => 0,
|
||||
'max_attempts' => 3,
|
||||
'retry_backoff_seconds' => 60,
|
||||
'stale_after_seconds' => 120,
|
||||
'queued_at' => now(),
|
||||
'available_at' => now(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user