mirror of
https://github.com/vitodeploy/vito.git
synced 2025-04-19 09:51:37 +00:00
Add workers to servers (#547)
This commit is contained in:
parent
48ae561ea4
commit
72352aad8d
@ -12,7 +12,7 @@ class SyncDatabaseUsers
|
|||||||
public function sync(Server $server): void
|
public function sync(Server $server): void
|
||||||
{
|
{
|
||||||
$service = $server->database();
|
$service = $server->database();
|
||||||
if (! $service) {
|
if (! $service instanceof \App\Models\Service) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/** @var Database $handler */
|
/** @var Database $handler */
|
||||||
|
@ -12,7 +12,7 @@ class SyncDatabases
|
|||||||
public function sync(Server $server): void
|
public function sync(Server $server): void
|
||||||
{
|
{
|
||||||
$service = $server->database();
|
$service = $server->database();
|
||||||
if (! $service) {
|
if (! $service instanceof \App\Models\Service) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
/** @var Database $handler */
|
/** @var Database $handler */
|
||||||
|
@ -1,13 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Actions\Queue;
|
|
||||||
|
|
||||||
use App\Models\Queue;
|
|
||||||
|
|
||||||
class DeleteQueue
|
|
||||||
{
|
|
||||||
public function delete(Queue $queue): void
|
|
||||||
{
|
|
||||||
$queue->delete();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Actions\Queue;
|
|
||||||
|
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Service;
|
|
||||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
|
||||||
|
|
||||||
class GetQueueLogs
|
|
||||||
{
|
|
||||||
public function getLogs(Queue $queue): string
|
|
||||||
{
|
|
||||||
/** @var Service $service */
|
|
||||||
$service = $queue->server->processManager();
|
|
||||||
|
|
||||||
/** @var ProcessManager $handler */
|
|
||||||
$handler = $service->handler();
|
|
||||||
|
|
||||||
return $handler->getLogs($queue->user, $queue->getLogFile());
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Actions\Queue;
|
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Service;
|
|
||||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
|
||||||
|
|
||||||
class ManageQueue
|
|
||||||
{
|
|
||||||
public function start(Queue $queue): void
|
|
||||||
{
|
|
||||||
$queue->status = QueueStatus::STARTING;
|
|
||||||
$queue->save();
|
|
||||||
dispatch(function () use ($queue): void {
|
|
||||||
/** @var Service $service */
|
|
||||||
$service = $queue->server->processManager();
|
|
||||||
/** @var ProcessManager $handler */
|
|
||||||
$handler = $service->handler();
|
|
||||||
$handler->start($queue->id, $queue->site_id);
|
|
||||||
$queue->status = QueueStatus::RUNNING;
|
|
||||||
$queue->save();
|
|
||||||
})->onConnection('ssh');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function stop(Queue $queue): void
|
|
||||||
{
|
|
||||||
$queue->status = QueueStatus::STOPPING;
|
|
||||||
$queue->save();
|
|
||||||
dispatch(function () use ($queue): void {
|
|
||||||
/** @var Service $service */
|
|
||||||
$service = $queue->server->processManager();
|
|
||||||
/** @var ProcessManager $handler */
|
|
||||||
$handler = $service->handler();
|
|
||||||
$handler->stop($queue->id, $queue->site_id);
|
|
||||||
$queue->status = QueueStatus::STOPPED;
|
|
||||||
$queue->save();
|
|
||||||
})->onConnection('ssh');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function restart(Queue $queue): void
|
|
||||||
{
|
|
||||||
$queue->status = QueueStatus::RESTARTING;
|
|
||||||
$queue->save();
|
|
||||||
dispatch(function () use ($queue): void {
|
|
||||||
/** @var Service $service */
|
|
||||||
$service = $queue->server->processManager();
|
|
||||||
/** @var ProcessManager $handler */
|
|
||||||
$handler = $service->handler();
|
|
||||||
$handler->restart($queue->id, $queue->site_id);
|
|
||||||
$queue->status = QueueStatus::RUNNING;
|
|
||||||
$queue->save();
|
|
||||||
})->onConnection('ssh');
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,63 +1,63 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Actions\Queue;
|
namespace App\Actions\Worker;
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
use App\Enums\WorkerStatus;
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Models\Worker;
|
||||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class EditQueue
|
class CreateWorker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param array<string, mixed> $input
|
* @param array<string, mixed> $input
|
||||||
*
|
*
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function edit(Queue $queue, array $input): void
|
public function create(Server $server, array $input, ?Site $site = null): void
|
||||||
{
|
{
|
||||||
$queue->fill([
|
$worker = new Worker([
|
||||||
|
'server_id' => $server->id,
|
||||||
|
'site_id' => $site?->id,
|
||||||
'command' => $input['command'],
|
'command' => $input['command'],
|
||||||
'user' => $input['user'],
|
'user' => $input['user'],
|
||||||
'auto_start' => $input['auto_start'] ? 1 : 0,
|
'auto_start' => $input['auto_start'] ? 1 : 0,
|
||||||
'auto_restart' => $input['auto_restart'] ? 1 : 0,
|
'auto_restart' => $input['auto_restart'] ? 1 : 0,
|
||||||
'numprocs' => $input['numprocs'],
|
'numprocs' => $input['numprocs'],
|
||||||
'status' => QueueStatus::RESTARTING,
|
'status' => WorkerStatus::CREATING,
|
||||||
]);
|
]);
|
||||||
$queue->save();
|
$worker->save();
|
||||||
|
|
||||||
dispatch(function () use ($queue): void {
|
dispatch(function () use ($worker): void {
|
||||||
/** @var Service $service */
|
/** @var Service $service */
|
||||||
$service = $queue->server->processManager();
|
$service = $worker->server->processManager();
|
||||||
/** @var ProcessManager $processManager */
|
/** @var ProcessManager $processManager */
|
||||||
$processManager = $service->handler();
|
$processManager = $service->handler();
|
||||||
$processManager->delete($queue->id, $queue->site_id);
|
|
||||||
|
|
||||||
$processManager->create(
|
$processManager->create(
|
||||||
$queue->id,
|
$worker->id,
|
||||||
$queue->command,
|
$worker->command,
|
||||||
$queue->user,
|
$worker->user,
|
||||||
$queue->auto_start,
|
$worker->auto_start,
|
||||||
$queue->auto_restart,
|
$worker->auto_restart,
|
||||||
$queue->numprocs,
|
$worker->numprocs,
|
||||||
$queue->getLogFile(),
|
$worker->getLogFile(),
|
||||||
$queue->site_id
|
$worker->site_id
|
||||||
);
|
);
|
||||||
$queue->status = QueueStatus::RUNNING;
|
$worker->status = WorkerStatus::RUNNING;
|
||||||
$queue->save();
|
$worker->save();
|
||||||
})->catch(function () use ($queue): void {
|
})->catch(function () use ($worker): void {
|
||||||
$queue->status = QueueStatus::FAILED;
|
$worker->delete();
|
||||||
$queue->save();
|
|
||||||
})->onConnection('ssh');
|
})->onConnection('ssh');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, array<string>>
|
* @return array<string, array<string>>
|
||||||
*/
|
*/
|
||||||
public static function rules(Server $server): array
|
public static function rules(Server $server, ?Site $site = null): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'command' => [
|
'command' => [
|
||||||
@ -65,10 +65,7 @@ public static function rules(Server $server): array
|
|||||||
],
|
],
|
||||||
'user' => [
|
'user' => [
|
||||||
'required',
|
'required',
|
||||||
Rule::in([
|
Rule::in($site?->getSshUsers() ?? $server->getSshUsers()),
|
||||||
'root',
|
|
||||||
$server->ssh_user,
|
|
||||||
]),
|
|
||||||
],
|
],
|
||||||
'numprocs' => [
|
'numprocs' => [
|
||||||
'required',
|
'required',
|
13
app/Actions/Worker/DeleteWorker.php
Normal file
13
app/Actions/Worker/DeleteWorker.php
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Worker;
|
||||||
|
|
||||||
|
use App\Models\Worker;
|
||||||
|
|
||||||
|
class DeleteWorker
|
||||||
|
{
|
||||||
|
public function delete(Worker $worker): void
|
||||||
|
{
|
||||||
|
$worker->delete();
|
||||||
|
}
|
||||||
|
}
|
@ -1,64 +1,64 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Actions\Queue;
|
namespace App\Actions\Worker;
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
use App\Enums\WorkerStatus;
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
|
use App\Models\Worker;
|
||||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||||
use Illuminate\Validation\Rule;
|
use Illuminate\Validation\Rule;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
|
|
||||||
class CreateQueue
|
class EditWorker
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* @param Server|Site $queueable
|
|
||||||
* @param array<string, mixed> $input
|
* @param array<string, mixed> $input
|
||||||
*
|
*
|
||||||
* @throws ValidationException
|
* @throws ValidationException
|
||||||
*/
|
*/
|
||||||
public function create(mixed $queueable, array $input): void
|
public function edit(Worker $worker, array $input): void
|
||||||
{
|
{
|
||||||
$queue = new Queue([
|
$worker->fill([
|
||||||
'server_id' => $queueable instanceof Server ? $queueable->id : $queueable->server_id,
|
|
||||||
'site_id' => $queueable instanceof Site ? $queueable->id : null,
|
|
||||||
'command' => $input['command'],
|
'command' => $input['command'],
|
||||||
'user' => $input['user'],
|
'user' => $input['user'],
|
||||||
'auto_start' => $input['auto_start'] ? 1 : 0,
|
'auto_start' => $input['auto_start'] ? 1 : 0,
|
||||||
'auto_restart' => $input['auto_restart'] ? 1 : 0,
|
'auto_restart' => $input['auto_restart'] ? 1 : 0,
|
||||||
'numprocs' => $input['numprocs'],
|
'numprocs' => $input['numprocs'],
|
||||||
'status' => QueueStatus::CREATING,
|
'status' => WorkerStatus::RESTARTING,
|
||||||
]);
|
]);
|
||||||
$queue->save();
|
$worker->save();
|
||||||
|
|
||||||
dispatch(function () use ($queue): void {
|
dispatch(function () use ($worker): void {
|
||||||
/** @var Service $service */
|
/** @var Service $service */
|
||||||
$service = $queue->server->processManager();
|
$service = $worker->server->processManager();
|
||||||
/** @var ProcessManager $processManager */
|
/** @var ProcessManager $processManager */
|
||||||
$processManager = $service->handler();
|
$processManager = $service->handler();
|
||||||
|
$processManager->delete($worker->id, $worker->site_id);
|
||||||
|
|
||||||
$processManager->create(
|
$processManager->create(
|
||||||
$queue->id,
|
$worker->id,
|
||||||
$queue->command,
|
$worker->command,
|
||||||
$queue->user,
|
$worker->user,
|
||||||
$queue->auto_start,
|
$worker->auto_start,
|
||||||
$queue->auto_restart,
|
$worker->auto_restart,
|
||||||
$queue->numprocs,
|
$worker->numprocs,
|
||||||
$queue->getLogFile(),
|
$worker->getLogFile(),
|
||||||
$queue->site_id
|
$worker->site_id
|
||||||
);
|
);
|
||||||
$queue->status = QueueStatus::RUNNING;
|
$worker->status = WorkerStatus::RUNNING;
|
||||||
$queue->save();
|
$worker->save();
|
||||||
})->catch(function () use ($queue): void {
|
})->catch(function () use ($worker): void {
|
||||||
$queue->delete();
|
$worker->status = WorkerStatus::FAILED;
|
||||||
|
$worker->save();
|
||||||
})->onConnection('ssh');
|
})->onConnection('ssh');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return array<string, array<string>>
|
* @return array<string, array<string>>
|
||||||
*/
|
*/
|
||||||
public static function rules(Site $site): array
|
public static function rules(Server $server, ?Site $site = null): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'command' => [
|
'command' => [
|
||||||
@ -66,10 +66,7 @@ public static function rules(Site $site): array
|
|||||||
],
|
],
|
||||||
'user' => [
|
'user' => [
|
||||||
'required',
|
'required',
|
||||||
Rule::in([
|
Rule::in($site?->getSshUsers() ?? $server->getSshUsers()),
|
||||||
'root',
|
|
||||||
$site->user,
|
|
||||||
]),
|
|
||||||
],
|
],
|
||||||
'numprocs' => [
|
'numprocs' => [
|
||||||
'required',
|
'required',
|
21
app/Actions/Worker/GetWorkerLogs.php
Normal file
21
app/Actions/Worker/GetWorkerLogs.php
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Worker;
|
||||||
|
|
||||||
|
use App\Models\Service;
|
||||||
|
use App\Models\Worker;
|
||||||
|
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||||
|
|
||||||
|
class GetWorkerLogs
|
||||||
|
{
|
||||||
|
public function getLogs(Worker $worker): string
|
||||||
|
{
|
||||||
|
/** @var Service $service */
|
||||||
|
$service = $worker->server->processManager();
|
||||||
|
|
||||||
|
/** @var ProcessManager $handler */
|
||||||
|
$handler = $service->handler();
|
||||||
|
|
||||||
|
return $handler->getLogs($worker->user, $worker->getLogFile());
|
||||||
|
}
|
||||||
|
}
|
56
app/Actions/Worker/ManageWorker.php
Normal file
56
app/Actions/Worker/ManageWorker.php
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Actions\Worker;
|
||||||
|
|
||||||
|
use App\Enums\WorkerStatus;
|
||||||
|
use App\Models\Service;
|
||||||
|
use App\Models\Worker;
|
||||||
|
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||||
|
|
||||||
|
class ManageWorker
|
||||||
|
{
|
||||||
|
public function start(Worker $worker): void
|
||||||
|
{
|
||||||
|
$worker->status = WorkerStatus::STARTING;
|
||||||
|
$worker->save();
|
||||||
|
dispatch(function () use ($worker): void {
|
||||||
|
/** @var Service $service */
|
||||||
|
$service = $worker->server->processManager();
|
||||||
|
/** @var ProcessManager $handler */
|
||||||
|
$handler = $service->handler();
|
||||||
|
$handler->start($worker->id, $worker->site_id);
|
||||||
|
$worker->status = WorkerStatus::RUNNING;
|
||||||
|
$worker->save();
|
||||||
|
})->onConnection('ssh');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function stop(Worker $worker): void
|
||||||
|
{
|
||||||
|
$worker->status = WorkerStatus::STOPPING;
|
||||||
|
$worker->save();
|
||||||
|
dispatch(function () use ($worker): void {
|
||||||
|
/** @var Service $service */
|
||||||
|
$service = $worker->server->processManager();
|
||||||
|
/** @var ProcessManager $handler */
|
||||||
|
$handler = $service->handler();
|
||||||
|
$handler->stop($worker->id, $worker->site_id);
|
||||||
|
$worker->status = WorkerStatus::STOPPED;
|
||||||
|
$worker->save();
|
||||||
|
})->onConnection('ssh');
|
||||||
|
}
|
||||||
|
|
||||||
|
public function restart(Worker $worker): void
|
||||||
|
{
|
||||||
|
$worker->status = WorkerStatus::RESTARTING;
|
||||||
|
$worker->save();
|
||||||
|
dispatch(function () use ($worker): void {
|
||||||
|
/** @var Service $service */
|
||||||
|
$service = $worker->server->processManager();
|
||||||
|
/** @var ProcessManager $handler */
|
||||||
|
$handler = $service->handler();
|
||||||
|
$handler->restart($worker->id, $worker->site_id);
|
||||||
|
$worker->status = WorkerStatus::RUNNING;
|
||||||
|
$worker->save();
|
||||||
|
})->onConnection('ssh');
|
||||||
|
}
|
||||||
|
}
|
@ -37,7 +37,7 @@ public function handle(): void
|
|||||||
$this->migrateModel(\App\Models\GitHook::class);
|
$this->migrateModel(\App\Models\GitHook::class);
|
||||||
$this->migrateModel(\App\Models\NotificationChannel::class);
|
$this->migrateModel(\App\Models\NotificationChannel::class);
|
||||||
$this->migrateModel(\App\Models\Project::class);
|
$this->migrateModel(\App\Models\Project::class);
|
||||||
$this->migrateModel(\App\Models\Queue::class);
|
$this->migrateModel(\App\Models\Worker::class);
|
||||||
$this->migrateModel(\App\Models\Server::class);
|
$this->migrateModel(\App\Models\Server::class);
|
||||||
$this->migrateModel(\App\Models\ServerLog::class);
|
$this->migrateModel(\App\Models\ServerLog::class);
|
||||||
$this->migrateModel(\App\Models\ServerProvider::class);
|
$this->migrateModel(\App\Models\ServerProvider::class);
|
||||||
|
@ -26,7 +26,5 @@ protected function schedule(Schedule $schedule): void
|
|||||||
protected function commands(): void
|
protected function commands(): void
|
||||||
{
|
{
|
||||||
$this->load(__DIR__.'/Commands');
|
$this->load(__DIR__.'/Commands');
|
||||||
|
|
||||||
require base_path('routes/console.php');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,7 +10,7 @@ final class SiteFeature
|
|||||||
|
|
||||||
const SSL = 'ssl';
|
const SSL = 'ssl';
|
||||||
|
|
||||||
const QUEUES = 'queues';
|
const WORKERS = 'workers';
|
||||||
|
|
||||||
const COMMANDS = 'commands';
|
const COMMANDS = 'commands';
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
namespace App\Enums;
|
namespace App\Enums;
|
||||||
|
|
||||||
final class QueueStatus
|
final class WorkerStatus
|
||||||
{
|
{
|
||||||
const RUNNING = 'running';
|
const RUNNING = 'running';
|
||||||
|
|
@ -58,7 +58,7 @@
|
|||||||
* @property Collection<int, DatabaseUser> $databaseUsers
|
* @property Collection<int, DatabaseUser> $databaseUsers
|
||||||
* @property Collection<int, FirewallRule> $firewallRules
|
* @property Collection<int, FirewallRule> $firewallRules
|
||||||
* @property Collection<int, CronJob> $cronJobs
|
* @property Collection<int, CronJob> $cronJobs
|
||||||
* @property Collection<int, Queue> $queues
|
* @property Collection<int, Worker> $queues
|
||||||
* @property Collection<int, Backup> $backups
|
* @property Collection<int, Backup> $backups
|
||||||
* @property Collection<int, SshKey> $sshKeys
|
* @property Collection<int, SshKey> $sshKeys
|
||||||
* @property Collection<int, Tag> $tags
|
* @property Collection<int, Tag> $tags
|
||||||
@ -125,7 +125,7 @@ public static function boot(): void
|
|||||||
try {
|
try {
|
||||||
$server->sites()->each(function ($site): void {
|
$server->sites()->each(function ($site): void {
|
||||||
/** @var Site $site */
|
/** @var Site $site */
|
||||||
$site->queues()->delete();
|
$site->workers()->delete();
|
||||||
$site->ssls()->delete();
|
$site->ssls()->delete();
|
||||||
$site->deployments()->delete();
|
$site->deployments()->delete();
|
||||||
$site->deploymentScript()->delete();
|
$site->deploymentScript()->delete();
|
||||||
@ -140,7 +140,7 @@ public static function boot(): void
|
|||||||
$server->databaseUsers()->delete();
|
$server->databaseUsers()->delete();
|
||||||
$server->firewallRules()->delete();
|
$server->firewallRules()->delete();
|
||||||
$server->cronJobs()->delete();
|
$server->cronJobs()->delete();
|
||||||
$server->queues()->delete();
|
$server->workers()->delete();
|
||||||
$server->daemons()->delete();
|
$server->daemons()->delete();
|
||||||
$server->sshKeys()->detach();
|
$server->sshKeys()->detach();
|
||||||
if (File::exists($server->sshKey()['public_key_path'])) {
|
if (File::exists($server->sshKey()['public_key_path'])) {
|
||||||
@ -265,11 +265,11 @@ public function cronJobs(): HasMany
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return HasMany<Queue, covariant $this>
|
* @return HasMany<Worker, covariant $this>
|
||||||
*/
|
*/
|
||||||
public function queues(): HasMany
|
public function workers(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Queue::class);
|
return $this->hasMany(Worker::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -281,11 +281,11 @@ public function backups(): HasMany
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return HasMany<Queue, covariant $this>
|
* @return HasMany<Worker, covariant $this>
|
||||||
*/
|
*/
|
||||||
public function daemons(): HasMany
|
public function daemons(): HasMany
|
||||||
{
|
{
|
||||||
return $this->queues()->whereNull('site_id');
|
return $this->workers()->whereNull('site_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
use App\SSH\Services\PHP\PHP;
|
use App\SSH\Services\PHP\PHP;
|
||||||
use App\SSH\Services\Webserver\Webserver;
|
use App\SSH\Services\Webserver\Webserver;
|
||||||
use App\Traits\HasProjectThroughServer;
|
use App\Traits\HasProjectThroughServer;
|
||||||
|
use Database\Factories\SiteFactory;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||||
@ -44,7 +45,7 @@
|
|||||||
* @property Collection<int, Command> $commands
|
* @property Collection<int, Command> $commands
|
||||||
* @property ?GitHook $gitHook
|
* @property ?GitHook $gitHook
|
||||||
* @property ?DeploymentScript $deploymentScript
|
* @property ?DeploymentScript $deploymentScript
|
||||||
* @property Collection<int, Queue> $queues
|
* @property Collection<int, Worker> $workers
|
||||||
* @property Collection<int, Ssl> $ssls
|
* @property Collection<int, Ssl> $ssls
|
||||||
* @property ?Ssl $activeSsl
|
* @property ?Ssl $activeSsl
|
||||||
* @property string $ssh_key_name
|
* @property string $ssh_key_name
|
||||||
@ -54,7 +55,7 @@
|
|||||||
*/
|
*/
|
||||||
class Site extends AbstractModel
|
class Site extends AbstractModel
|
||||||
{
|
{
|
||||||
/** @use HasFactory<\Database\Factories\SiteFactory> */
|
/** @use HasFactory<SiteFactory> */
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
use HasProjectThroughServer;
|
use HasProjectThroughServer;
|
||||||
@ -105,9 +106,9 @@ public static function boot(): void
|
|||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
static::deleting(function (Site $site): void {
|
static::deleting(function (Site $site): void {
|
||||||
$site->queues()->each(function ($queue): void {
|
$site->workers()->each(function ($worker): void {
|
||||||
/** @var Queue $queue */
|
/** @var Worker $worker */
|
||||||
$queue->delete();
|
$worker->delete();
|
||||||
});
|
});
|
||||||
$site->ssls()->delete();
|
$site->ssls()->delete();
|
||||||
$site->deployments()->delete();
|
$site->deployments()->delete();
|
||||||
@ -186,11 +187,11 @@ public function deploymentScript(): HasOne
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return HasMany<Queue, covariant $this>
|
* @return HasMany<Worker, covariant $this>
|
||||||
*/
|
*/
|
||||||
public function queues(): HasMany
|
public function workers(): HasMany
|
||||||
{
|
{
|
||||||
return $this->hasMany(Queue::class);
|
return $this->hasMany(Worker::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -401,4 +402,21 @@ public function loadBalancerServers(): HasMany
|
|||||||
{
|
{
|
||||||
return $this->hasMany(LoadBalancerServer::class, 'load_balancer_id');
|
return $this->hasMany(LoadBalancerServer::class, 'load_balancer_id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array<string>
|
||||||
|
*/
|
||||||
|
public function getSshUsers(): array
|
||||||
|
{
|
||||||
|
$users = [
|
||||||
|
'root',
|
||||||
|
$this->server->getSshUser(),
|
||||||
|
];
|
||||||
|
|
||||||
|
if ($this->isIsolated()) {
|
||||||
|
$users[] = $this->user;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $users;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@
|
|||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
use App\Enums\WorkerStatus;
|
||||||
use App\SSH\Services\ProcessManager\ProcessManager;
|
use App\SSH\Services\ProcessManager\ProcessManager;
|
||||||
use Database\Factories\QueueFactory;
|
use Database\Factories\WorkerFactory;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||||
use Illuminate\Support\Facades\Log;
|
use Illuminate\Support\Facades\Log;
|
||||||
@ -24,9 +24,9 @@
|
|||||||
* @property Server $server
|
* @property Server $server
|
||||||
* @property Site $site
|
* @property Site $site
|
||||||
*/
|
*/
|
||||||
class Queue extends AbstractModel
|
class Worker extends AbstractModel
|
||||||
{
|
{
|
||||||
/** @use HasFactory<QueueFactory> */
|
/** @use HasFactory<WorkerFactory> */
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
|
||||||
protected $fillable = [
|
protected $fillable = [
|
||||||
@ -55,28 +55,28 @@ class Queue extends AbstractModel
|
|||||||
* @var array<string, string>
|
* @var array<string, string>
|
||||||
*/
|
*/
|
||||||
public static array $statusColors = [
|
public static array $statusColors = [
|
||||||
QueueStatus::RUNNING => 'success',
|
WorkerStatus::RUNNING => 'success',
|
||||||
QueueStatus::CREATING => 'warning',
|
WorkerStatus::CREATING => 'warning',
|
||||||
QueueStatus::DELETING => 'warning',
|
WorkerStatus::DELETING => 'warning',
|
||||||
QueueStatus::FAILED => 'danger',
|
WorkerStatus::FAILED => 'danger',
|
||||||
QueueStatus::STARTING => 'warning',
|
WorkerStatus::STARTING => 'warning',
|
||||||
QueueStatus::STOPPING => 'warning',
|
WorkerStatus::STOPPING => 'warning',
|
||||||
QueueStatus::RESTARTING => 'warning',
|
WorkerStatus::RESTARTING => 'warning',
|
||||||
QueueStatus::STOPPED => 'gray',
|
WorkerStatus::STOPPED => 'gray',
|
||||||
];
|
];
|
||||||
|
|
||||||
public static function boot(): void
|
public static function boot(): void
|
||||||
{
|
{
|
||||||
parent::boot();
|
parent::boot();
|
||||||
|
|
||||||
static::deleting(function (Queue $queue): void {
|
static::deleting(function (Worker $worker): void {
|
||||||
try {
|
try {
|
||||||
/** @var Service $service */
|
/** @var Service $service */
|
||||||
$service = $queue->server->processManager();
|
$service = $worker->server->processManager();
|
||||||
/** @var ProcessManager $handler */
|
/** @var ProcessManager $handler */
|
||||||
$handler = $service->handler();
|
$handler = $service->handler();
|
||||||
|
|
||||||
$handler->delete($queue->id, $queue->site_id);
|
$handler->delete($worker->id, $worker->site_id);
|
||||||
} catch (Throwable $e) {
|
} catch (Throwable $e) {
|
||||||
Log::error($e);
|
Log::error($e);
|
||||||
}
|
}
|
@ -1,61 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Policies;
|
|
||||||
|
|
||||||
use App\Enums\SiteFeature;
|
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Server;
|
|
||||||
use App\Models\Site;
|
|
||||||
use App\Models\User;
|
|
||||||
use Illuminate\Auth\Access\HandlesAuthorization;
|
|
||||||
|
|
||||||
class QueuePolicy
|
|
||||||
{
|
|
||||||
use HandlesAuthorization;
|
|
||||||
|
|
||||||
public function viewAny(User $user, Site $site, Server $server): bool
|
|
||||||
{
|
|
||||||
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
|
||||||
$server->isReady() &&
|
|
||||||
$site->hasFeature(SiteFeature::QUEUES) &&
|
|
||||||
$site->isReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function view(User $user, Queue $queue, Site $site, Server $server): bool
|
|
||||||
{
|
|
||||||
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
|
||||||
$site->server_id === $server->id &&
|
|
||||||
$server->isReady() &&
|
|
||||||
$site->isReady() &&
|
|
||||||
$site->hasFeature(SiteFeature::QUEUES) &&
|
|
||||||
$queue->site_id === $site->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function create(User $user, Site $site, Server $server): bool
|
|
||||||
{
|
|
||||||
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
|
||||||
$server->isReady() &&
|
|
||||||
$site->hasFeature(SiteFeature::QUEUES) &&
|
|
||||||
$site->isReady();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function update(User $user, Queue $queue, Site $site, Server $server): bool
|
|
||||||
{
|
|
||||||
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
|
||||||
$site->server_id === $server->id &&
|
|
||||||
$server->isReady() &&
|
|
||||||
$site->isReady() &&
|
|
||||||
$site->hasFeature(SiteFeature::QUEUES) &&
|
|
||||||
$queue->site_id === $site->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public function delete(User $user, Queue $queue, Site $site, Server $server): bool
|
|
||||||
{
|
|
||||||
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
|
||||||
$site->server_id === $server->id &&
|
|
||||||
$server->isReady() &&
|
|
||||||
$site->isReady() &&
|
|
||||||
$site->hasFeature(SiteFeature::QUEUES) &&
|
|
||||||
$queue->site_id === $site->id;
|
|
||||||
}
|
|
||||||
}
|
|
86
app/Policies/WorkerPolicy.php
Normal file
86
app/Policies/WorkerPolicy.php
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Enums\SiteFeature;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\Site;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Models\Worker;
|
||||||
|
use Illuminate\Auth\Access\HandlesAuthorization;
|
||||||
|
|
||||||
|
class WorkerPolicy
|
||||||
|
{
|
||||||
|
use HandlesAuthorization;
|
||||||
|
|
||||||
|
public function viewAny(User $user, Server $server, ?Site $site = null): bool
|
||||||
|
{
|
||||||
|
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
||||||
|
$server->isReady() &&
|
||||||
|
(
|
||||||
|
! $site instanceof \App\Models\Site ||
|
||||||
|
(
|
||||||
|
$site->hasFeature(SiteFeature::WORKERS) &&
|
||||||
|
$site->isReady()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function view(User $user, Worker $worker, Server $server, ?Site $site = null): bool
|
||||||
|
{
|
||||||
|
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
||||||
|
$site->server_id === $server->id &&
|
||||||
|
$server->isReady() &&
|
||||||
|
(
|
||||||
|
! $site instanceof \App\Models\Site ||
|
||||||
|
(
|
||||||
|
$site->hasFeature(SiteFeature::WORKERS) &&
|
||||||
|
$site->isReady() &&
|
||||||
|
$worker->site_id === $site->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function create(User $user, Server $server, ?Site $site = null): bool
|
||||||
|
{
|
||||||
|
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
||||||
|
$server->isReady() &&
|
||||||
|
(
|
||||||
|
! $site instanceof \App\Models\Site ||
|
||||||
|
(
|
||||||
|
$site->hasFeature(SiteFeature::WORKERS) &&
|
||||||
|
$site->isReady()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function update(User $user, Worker $worker, Server $server, ?Site $site = null): bool
|
||||||
|
{
|
||||||
|
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
||||||
|
$site->server_id === $server->id &&
|
||||||
|
$server->isReady() &&
|
||||||
|
(
|
||||||
|
! $site instanceof \App\Models\Site ||
|
||||||
|
(
|
||||||
|
$site->hasFeature(SiteFeature::WORKERS) &&
|
||||||
|
$site->isReady() &&
|
||||||
|
$worker->site_id === $site->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function delete(User $user, Worker $worker, Server $server, ?Site $site = null): bool
|
||||||
|
{
|
||||||
|
return ($user->isAdmin() || $server->project->users->contains($user)) &&
|
||||||
|
$site->server_id === $server->id &&
|
||||||
|
$server->isReady() &&
|
||||||
|
(
|
||||||
|
! $site instanceof \App\Models\Site ||
|
||||||
|
(
|
||||||
|
$site->hasFeature(SiteFeature::WORKERS) &&
|
||||||
|
$site->isReady() &&
|
||||||
|
$worker->site_id === $site->id
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@ -286,7 +286,7 @@ public function getCharsets(): array
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($results as $charset => $value) {
|
foreach (array_keys($results) as $charset) {
|
||||||
$results[$charset]['list'] = $charsetCollations[$charset];
|
$results[$charset]['list'] = $charsetCollations[$charset];
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,9 +310,7 @@ public function getDatabases(): array
|
|||||||
|
|
||||||
$databases = $this->tableToArray($data);
|
$databases = $this->tableToArray($data);
|
||||||
|
|
||||||
return array_values(array_filter($databases, function ($database) {
|
return array_values(array_filter($databases, fn ($database): bool => ! in_array($database[0], $this->systemDbs)));
|
||||||
return ! in_array($database[0], $this->systemDbs);
|
|
||||||
}));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,15 +325,11 @@ public function getUsers(): array
|
|||||||
|
|
||||||
$users = $this->tableToArray($data);
|
$users = $this->tableToArray($data);
|
||||||
|
|
||||||
$users = array_values(array_filter($users, function ($users) {
|
$users = array_values(array_filter($users, fn ($users): bool => ! in_array($users[0], $this->systemUsers)));
|
||||||
return ! in_array($users[0], $this->systemUsers);
|
|
||||||
}));
|
|
||||||
|
|
||||||
foreach ($users as $key => $user) {
|
foreach ($users as $key => $user) {
|
||||||
$databases = explode(',', $user[2]);
|
$databases = explode(',', $user[2]);
|
||||||
$databases = array_values(array_filter($databases, function ($database) {
|
$databases = array_values(array_filter($databases, fn ($database): bool => ! in_array($database, $this->systemDbs)));
|
||||||
return ! in_array($database, $this->systemDbs);
|
|
||||||
}));
|
|
||||||
$users[$key][2] = implode(',', $databases);
|
$users[$key][2] = implode(',', $databases);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,9 +27,9 @@ public function deletionRules(): array
|
|||||||
return [
|
return [
|
||||||
'service' => [
|
'service' => [
|
||||||
function (string $attribute, mixed $value, Closure $fail): void {
|
function (string $attribute, mixed $value, Closure $fail): void {
|
||||||
$hasQueue = $this->service->server->queues()->exists();
|
$hasWorker = $this->service->server->workers()->exists();
|
||||||
if ($hasQueue) {
|
if ($hasWorker) {
|
||||||
$fail('You have queue(s) on the server.');
|
$fail('You have worker(s) on the server.');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
@ -34,9 +34,9 @@ public function baseCommands(): array
|
|||||||
'name' => 'Clear Application Cache Only',
|
'name' => 'Clear Application Cache Only',
|
||||||
'command' => 'php artisan cache:clear',
|
'command' => 'php artisan cache:clear',
|
||||||
],
|
],
|
||||||
// Queue Commands
|
// Worker Commands
|
||||||
[
|
[
|
||||||
'name' => 'Restart Queue Workers',
|
'name' => 'Restart Workers',
|
||||||
'command' => 'php artisan queue:restart',
|
'command' => 'php artisan queue:restart',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
@ -15,7 +15,7 @@ public function supportedFeatures(): array
|
|||||||
SiteFeature::COMMANDS,
|
SiteFeature::COMMANDS,
|
||||||
SiteFeature::ENV,
|
SiteFeature::ENV,
|
||||||
SiteFeature::SSL,
|
SiteFeature::SSL,
|
||||||
SiteFeature::QUEUES,
|
SiteFeature::WORKERS,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -23,7 +23,7 @@ public function supportedFeatures(): array
|
|||||||
SiteFeature::COMMANDS,
|
SiteFeature::COMMANDS,
|
||||||
SiteFeature::ENV,
|
SiteFeature::ENV,
|
||||||
SiteFeature::SSL,
|
SiteFeature::SSL,
|
||||||
SiteFeature::QUEUES,
|
SiteFeature::WORKERS,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -94,8 +94,8 @@ protected function getHeaderActions(): array
|
|||||||
->requiresConfirmation()
|
->requiresConfirmation()
|
||||||
->modalDescription('This will create databases that exist on the server but not in Vito.')
|
->modalDescription('This will create databases that exist on the server but not in Vito.')
|
||||||
->modalSubmitActionLabel('Sync')
|
->modalSubmitActionLabel('Sync')
|
||||||
->action(function () {
|
->action(function (): void {
|
||||||
run_action($this, function () {
|
run_action($this, function (): void {
|
||||||
app(SyncDatabases::class)->sync($this->server);
|
app(SyncDatabases::class)->sync($this->server);
|
||||||
|
|
||||||
$this->dispatch('$refresh');
|
$this->dispatch('$refresh');
|
||||||
|
@ -38,8 +38,8 @@ protected function getHeaderActions(): array
|
|||||||
->requiresConfirmation()
|
->requiresConfirmation()
|
||||||
->modalDescription('This will create db users that exist on the server but not in Vito.')
|
->modalDescription('This will create db users that exist on the server but not in Vito.')
|
||||||
->modalSubmitActionLabel('Sync')
|
->modalSubmitActionLabel('Sync')
|
||||||
->action(function () {
|
->action(function (): void {
|
||||||
run_action($this, function () {
|
run_action($this, function (): void {
|
||||||
app(SyncDatabaseUsers::class)->sync($this->server);
|
app(SyncDatabaseUsers::class)->sync($this->server);
|
||||||
|
|
||||||
$this->dispatch('$refresh');
|
$this->dispatch('$refresh');
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
use App\Models\SshKey;
|
use App\Models\SshKey;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Worker;
|
||||||
use App\Web\Components\Page as BasePage;
|
use App\Web\Components\Page as BasePage;
|
||||||
use App\Web\Pages\Servers\Console\Index as ConsoleIndex;
|
use App\Web\Pages\Servers\Console\Index as ConsoleIndex;
|
||||||
use App\Web\Pages\Servers\CronJobs\Index as CronJobsIndex;
|
use App\Web\Pages\Servers\CronJobs\Index as CronJobsIndex;
|
||||||
@ -28,6 +29,7 @@
|
|||||||
use App\Web\Pages\Servers\SSHKeys\Index as SshKeysIndex;
|
use App\Web\Pages\Servers\SSHKeys\Index as SshKeysIndex;
|
||||||
use App\Web\Pages\Servers\View as ServerView;
|
use App\Web\Pages\Servers\View as ServerView;
|
||||||
use App\Web\Pages\Servers\Widgets\ServerSummary;
|
use App\Web\Pages\Servers\Widgets\ServerSummary;
|
||||||
|
use App\Web\Pages\Servers\Workers\Index as WorkersIndex;
|
||||||
use Filament\Navigation\NavigationItem;
|
use Filament\Navigation\NavigationItem;
|
||||||
|
|
||||||
abstract class Page extends BasePage
|
abstract class Page extends BasePage
|
||||||
@ -99,6 +101,13 @@ public function getSubNavigation(): array
|
|||||||
->url(CronJobsIndex::getUrl(parameters: ['server' => $this->server]));
|
->url(CronJobsIndex::getUrl(parameters: ['server' => $this->server]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($user->can('viewAny', [Worker::class, $this->server])) {
|
||||||
|
$items[] = NavigationItem::make(WorkersIndex::getNavigationLabel())
|
||||||
|
->icon('heroicon-o-queue-list')
|
||||||
|
->isActiveWhen(fn () => request()->routeIs(WorkersIndex::getRouteName().'*'))
|
||||||
|
->url(WorkersIndex::getUrl(parameters: ['server' => $this->server]));
|
||||||
|
}
|
||||||
|
|
||||||
if ($user->can('viewAnyServer', [SshKey::class, $this->server])) {
|
if ($user->can('viewAnyServer', [SshKey::class, $this->server])) {
|
||||||
$items[] = NavigationItem::make(SshKeysIndex::getNavigationLabel())
|
$items[] = NavigationItem::make(SshKeysIndex::getNavigationLabel())
|
||||||
->icon('heroicon-o-key')
|
->icon('heroicon-o-key')
|
||||||
|
@ -2,11 +2,11 @@
|
|||||||
|
|
||||||
namespace App\Web\Pages\Servers\Sites;
|
namespace App\Web\Pages\Servers\Sites;
|
||||||
|
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\ServerLog;
|
use App\Models\ServerLog;
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
use App\Models\Ssl;
|
use App\Models\Ssl;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Worker;
|
||||||
use App\Web\Contracts\HasSecondSubNav;
|
use App\Web\Contracts\HasSecondSubNav;
|
||||||
use App\Web\Pages\Servers\Page as BasePage;
|
use App\Web\Pages\Servers\Page as BasePage;
|
||||||
use App\Web\Pages\Servers\Sites\Widgets\SiteSummary;
|
use App\Web\Pages\Servers\Sites\Widgets\SiteSummary;
|
||||||
@ -45,11 +45,11 @@ public function getSecondSubNavigation(): array
|
|||||||
]));
|
]));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user->can('viewAny', [Queue::class, $this->site, $this->server])) {
|
if ($user->can('viewAny', [Worker::class, $this->server, $this->site])) {
|
||||||
$items[] = NavigationItem::make(Pages\Queues\Index::getNavigationLabel())
|
$items[] = NavigationItem::make(Pages\Workers\Index::getNavigationLabel())
|
||||||
->icon('heroicon-o-queue-list')
|
->icon('heroicon-o-queue-list')
|
||||||
->isActiveWhen(fn () => request()->routeIs(Pages\Queues\Index::getRouteName()))
|
->isActiveWhen(fn () => request()->routeIs(Pages\Workers\Index::getRouteName()))
|
||||||
->url(Pages\Queues\Index::getUrl(parameters: [
|
->url(Pages\Workers\Index::getUrl(parameters: [
|
||||||
'server' => $this->server,
|
'server' => $this->server,
|
||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
]));
|
]));
|
||||||
|
@ -1,79 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
namespace App\Web\Pages\Servers\Sites\Pages\Queues;
|
|
||||||
|
|
||||||
use App\Actions\Queue\CreateQueue;
|
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Web\Pages\Servers\Sites\Page;
|
|
||||||
use Filament\Actions\Action;
|
|
||||||
use Filament\Actions\CreateAction;
|
|
||||||
use Filament\Forms\Components\Checkbox;
|
|
||||||
use Filament\Forms\Components\Grid;
|
|
||||||
use Filament\Forms\Components\Select;
|
|
||||||
use Filament\Forms\Components\TextInput;
|
|
||||||
use Filament\Support\Enums\MaxWidth;
|
|
||||||
|
|
||||||
class Index extends Page
|
|
||||||
{
|
|
||||||
protected static ?string $slug = 'servers/{server}/sites/{site}/queues';
|
|
||||||
|
|
||||||
protected static ?string $title = 'Queues';
|
|
||||||
|
|
||||||
public function mount(): void
|
|
||||||
{
|
|
||||||
$this->authorize('viewAny', [Queue::class, $this->site, $this->server]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public function getWidgets(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
[Widgets\QueuesList::class, ['site' => $this->site]],
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
protected function getHeaderActions(): array
|
|
||||||
{
|
|
||||||
return [
|
|
||||||
Action::make('read-the-docs')
|
|
||||||
->label('Read the Docs')
|
|
||||||
->icon('heroicon-o-document-text')
|
|
||||||
->color('gray')
|
|
||||||
->url('https://vitodeploy.com/sites/queues')
|
|
||||||
->openUrlInNewTab(),
|
|
||||||
CreateAction::make('create')
|
|
||||||
->icon('heroicon-o-plus')
|
|
||||||
->createAnother(false)
|
|
||||||
->modalWidth(MaxWidth::ExtraLarge)
|
|
||||||
->label('New Queue')
|
|
||||||
->form([
|
|
||||||
TextInput::make('command')
|
|
||||||
->rules(CreateQueue::rules($this->site)['command'])
|
|
||||||
->helperText('Example: php /home/vito/your-site/artisan queue:work'),
|
|
||||||
Select::make('user')
|
|
||||||
->rules(fn (callable $get) => CreateQueue::rules($this->site)['user'])
|
|
||||||
->options([
|
|
||||||
'root' => 'root',
|
|
||||||
$this->site->user => $this->site->user,
|
|
||||||
]),
|
|
||||||
TextInput::make('numprocs')
|
|
||||||
->default(1)
|
|
||||||
->rules(CreateQueue::rules($this->site)['numprocs'])
|
|
||||||
->helperText('Number of processes'),
|
|
||||||
Grid::make()
|
|
||||||
->schema([
|
|
||||||
Checkbox::make('auto_start')
|
|
||||||
->default(false),
|
|
||||||
Checkbox::make('auto_restart')
|
|
||||||
->default(false),
|
|
||||||
]),
|
|
||||||
])
|
|
||||||
->using(function (array $data): void {
|
|
||||||
run_action($this, function () use ($data): void {
|
|
||||||
app(CreateQueue::class)->create($this->site, $data);
|
|
||||||
|
|
||||||
$this->dispatch('$refresh');
|
|
||||||
});
|
|
||||||
}),
|
|
||||||
];
|
|
||||||
}
|
|
||||||
}
|
|
53
app/Web/Pages/Servers/Sites/Pages/Workers/Index.php
Normal file
53
app/Web/Pages/Servers/Sites/Pages/Workers/Index.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Web\Pages\Servers\Sites\Pages\Workers;
|
||||||
|
|
||||||
|
use App\Models\Worker;
|
||||||
|
use App\Web\Pages\Servers\Sites\Page;
|
||||||
|
use App\Web\Pages\Servers\Workers\Actions\Create;
|
||||||
|
use Filament\Actions\Action;
|
||||||
|
use Filament\Actions\CreateAction;
|
||||||
|
use Filament\Support\Enums\MaxWidth;
|
||||||
|
|
||||||
|
class Index extends Page
|
||||||
|
{
|
||||||
|
protected static ?string $slug = 'servers/{server}/sites/{site}/workers';
|
||||||
|
|
||||||
|
protected static ?string $title = 'Workers';
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', [Worker::class, $this->server, $this->site]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWidgets(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[Widgets\WorkersList::class, [
|
||||||
|
'server' => $this->server,
|
||||||
|
'site' => $this->site,
|
||||||
|
]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Action::make('read-the-docs')
|
||||||
|
->label('Read the Docs')
|
||||||
|
->icon('heroicon-o-document-text')
|
||||||
|
->color('gray')
|
||||||
|
->url('https://vitodeploy.com/servers/workers')
|
||||||
|
->openUrlInNewTab(),
|
||||||
|
CreateAction::make('create')
|
||||||
|
->icon('heroicon-o-plus')
|
||||||
|
->createAnother(false)
|
||||||
|
->modalWidth(MaxWidth::ExtraLarge)
|
||||||
|
->label('New Worker')
|
||||||
|
->form(Create::form($this->server, $this->site))
|
||||||
|
->using(fn (array $data) => run_action($this, function () use ($data): void {
|
||||||
|
Create::action($this, $data, $this->server, $this->site);
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,5 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Web\Pages\Servers\Sites\Pages\Workers\Widgets;
|
||||||
|
|
||||||
|
class WorkersList extends \App\Web\Pages\Servers\Workers\Widgets\WorkersList {}
|
55
app/Web/Pages/Servers/Workers/Actions/Create.php
Normal file
55
app/Web/Pages/Servers/Workers/Actions/Create.php
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Web\Pages\Servers\Workers\Actions;
|
||||||
|
|
||||||
|
use App\Actions\Worker\CreateWorker;
|
||||||
|
use App\Models\Server;
|
||||||
|
use App\Models\Site;
|
||||||
|
use Filament\Forms\Components\Checkbox;
|
||||||
|
use Filament\Forms\Components\Grid;
|
||||||
|
use Filament\Forms\Components\Select;
|
||||||
|
use Filament\Forms\Components\TextInput;
|
||||||
|
use Livewire\Component;
|
||||||
|
|
||||||
|
class Create
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return array<int, mixed>
|
||||||
|
*/
|
||||||
|
public static function form(Server $server, ?Site $site = null): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
TextInput::make('command')
|
||||||
|
->rules(CreateWorker::rules($server, $site)['command'])
|
||||||
|
->helperText('Example: php /home/vito/your-site/artisan queue:work'),
|
||||||
|
Select::make('user')
|
||||||
|
->rules(fn (callable $get) => CreateWorker::rules($server, $site)['user'])
|
||||||
|
->options($server->getSshUsers()),
|
||||||
|
TextInput::make('numprocs')
|
||||||
|
->default(1)
|
||||||
|
->rules(CreateWorker::rules($server, $site)['numprocs'])
|
||||||
|
->helperText('Number of processes'),
|
||||||
|
Grid::make()
|
||||||
|
->schema([
|
||||||
|
Checkbox::make('auto_start')
|
||||||
|
->default(false),
|
||||||
|
Checkbox::make('auto_restart')
|
||||||
|
->default(false),
|
||||||
|
]),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param array<string, mixed> $data
|
||||||
|
*/
|
||||||
|
public static function action(Component $component, array $data, Server $server, ?Site $site = null): void
|
||||||
|
{
|
||||||
|
app(CreateWorker::class)->create(
|
||||||
|
$server,
|
||||||
|
$data,
|
||||||
|
$site
|
||||||
|
);
|
||||||
|
|
||||||
|
$component->dispatch('$refresh');
|
||||||
|
}
|
||||||
|
}
|
50
app/Web/Pages/Servers/Workers/Index.php
Normal file
50
app/Web/Pages/Servers/Workers/Index.php
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Web\Pages\Servers\Workers;
|
||||||
|
|
||||||
|
use App\Models\Worker;
|
||||||
|
use App\Web\Pages\Servers\Page;
|
||||||
|
use App\Web\Pages\Servers\Workers\Actions\Create;
|
||||||
|
use Filament\Actions\Action;
|
||||||
|
use Filament\Actions\CreateAction;
|
||||||
|
use Filament\Support\Enums\MaxWidth;
|
||||||
|
|
||||||
|
class Index extends Page
|
||||||
|
{
|
||||||
|
protected static ?string $slug = 'servers/{server}/workers';
|
||||||
|
|
||||||
|
protected static ?string $title = 'Workers';
|
||||||
|
|
||||||
|
public function mount(): void
|
||||||
|
{
|
||||||
|
$this->authorize('viewAny', [Worker::class, $this->server]);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getWidgets(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
[Widgets\WorkersList::class, ['server' => $this->server]],
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function getHeaderActions(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
Action::make('read-the-docs')
|
||||||
|
->label('Read the Docs')
|
||||||
|
->icon('heroicon-o-document-text')
|
||||||
|
->color('gray')
|
||||||
|
->url('https://vitodeploy.com/servers/workers')
|
||||||
|
->openUrlInNewTab(),
|
||||||
|
CreateAction::make('create')
|
||||||
|
->icon('heroicon-o-plus')
|
||||||
|
->createAnother(false)
|
||||||
|
->modalWidth(MaxWidth::ExtraLarge)
|
||||||
|
->label('New Worker')
|
||||||
|
->form(Create::form($this->server))
|
||||||
|
->using(fn (array $data) => run_action($this, function () use ($data): void {
|
||||||
|
Create::action($this, $data, $this->server);
|
||||||
|
})),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -1,14 +1,15 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
namespace App\Web\Pages\Servers\Sites\Pages\Queues\Widgets;
|
namespace App\Web\Pages\Servers\Workers\Widgets;
|
||||||
|
|
||||||
use App\Actions\Queue\DeleteQueue;
|
use App\Actions\Worker\DeleteWorker;
|
||||||
use App\Actions\Queue\EditQueue;
|
use App\Actions\Worker\EditWorker;
|
||||||
use App\Actions\Queue\GetQueueLogs;
|
use App\Actions\Worker\GetWorkerLogs;
|
||||||
use App\Actions\Queue\ManageQueue;
|
use App\Actions\Worker\ManageWorker;
|
||||||
use App\Models\Queue;
|
use App\Models\Server;
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\Worker;
|
||||||
use Filament\Forms\Components\Checkbox;
|
use Filament\Forms\Components\Checkbox;
|
||||||
use Filament\Forms\Components\Grid;
|
use Filament\Forms\Components\Grid;
|
||||||
use Filament\Forms\Components\Select;
|
use Filament\Forms\Components\Select;
|
||||||
@ -24,9 +25,11 @@
|
|||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\View\ComponentAttributeBag;
|
use Illuminate\View\ComponentAttributeBag;
|
||||||
|
|
||||||
class QueuesList extends Widget
|
class WorkersList extends Widget
|
||||||
{
|
{
|
||||||
public Site $site;
|
public Server $server;
|
||||||
|
|
||||||
|
public ?Site $site = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var array<string>
|
* @var array<string>
|
||||||
@ -34,11 +37,17 @@ class QueuesList extends Widget
|
|||||||
protected $listeners = ['$refresh'];
|
protected $listeners = ['$refresh'];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return Builder<Queue>
|
* @return Builder<Worker>
|
||||||
*/
|
*/
|
||||||
protected function getTableQuery(): Builder
|
protected function getTableQuery(): Builder
|
||||||
{
|
{
|
||||||
return Queue::query()->where('site_id', $this->site->id);
|
return Worker::query()
|
||||||
|
->where('server_id', $this->server->id)
|
||||||
|
->where(function (Builder $query): void {
|
||||||
|
if ($this->site instanceof \App\Models\Site) {
|
||||||
|
$query->where('site_id', $this->site->id);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getTableColumns(): array
|
protected function getTableColumns(): array
|
||||||
@ -47,16 +56,16 @@ protected function getTableColumns(): array
|
|||||||
TextColumn::make('command')
|
TextColumn::make('command')
|
||||||
->limit(20)
|
->limit(20)
|
||||||
->copyable()
|
->copyable()
|
||||||
->tooltip(fn (Queue $record) => $record->command)
|
->tooltip(fn (Worker $record) => $record->command)
|
||||||
->searchable()
|
->searchable()
|
||||||
->sortable(),
|
->sortable(),
|
||||||
TextColumn::make('created_at')
|
TextColumn::make('created_at')
|
||||||
->formatStateUsing(fn (Queue $record) => $record->created_at_by_timezone)
|
->formatStateUsing(fn (Worker $record) => $record->created_at_by_timezone)
|
||||||
->sortable(),
|
->sortable(),
|
||||||
TextColumn::make('status')
|
TextColumn::make('status')
|
||||||
->label('Status')
|
->label('Status')
|
||||||
->badge()
|
->badge()
|
||||||
->color(fn (Queue $record) => Queue::$statusColors[$record->status])
|
->color(fn (Worker $record) => Worker::$statusColors[$record->status])
|
||||||
->searchable()
|
->searchable()
|
||||||
->sortable(),
|
->sortable(),
|
||||||
];
|
];
|
||||||
@ -86,12 +95,12 @@ private function operationAction(string $type, string $icon): Action
|
|||||||
$user = auth()->user();
|
$user = auth()->user();
|
||||||
|
|
||||||
return Action::make($type)
|
return Action::make($type)
|
||||||
->authorize(fn (Queue $record) => $user->can('update', [$record, $this->site, $this->site->server]))
|
->authorize(fn (Worker $record) => $user->can('update', [$record, $this->server, $this->site]))
|
||||||
->label(ucfirst($type).' queue')
|
->label(ucfirst($type).' worker')
|
||||||
->icon($icon)
|
->icon($icon)
|
||||||
->action(function (Queue $record) use ($type): void {
|
->action(function (Worker $record) use ($type): void {
|
||||||
run_action($this, function () use ($record, $type): void {
|
run_action($this, function () use ($record, $type): void {
|
||||||
app(ManageQueue::class)->$type($record);
|
app(ManageWorker::class)->$type($record);
|
||||||
$this->dispatch('$refresh');
|
$this->dispatch('$refresh');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -104,10 +113,10 @@ private function logsAction(): Action
|
|||||||
|
|
||||||
return Action::make('logs')
|
return Action::make('logs')
|
||||||
->icon('heroicon-o-eye')
|
->icon('heroicon-o-eye')
|
||||||
->authorize(fn (Queue $record) => $user->can('view', [$record, $this->site, $this->site->server]))
|
->authorize(fn (Worker $record) => $user->can('view', [$record, $this->server, $this->site]))
|
||||||
->modalHeading('View Log')
|
->modalHeading('View Log')
|
||||||
->modalContent(fn (Queue $record) => view('components.console-view', [
|
->modalContent(fn (Worker $record) => view('components.console-view', [
|
||||||
'slot' => app(GetQueueLogs::class)->getLogs($record),
|
'slot' => app(GetWorkerLogs::class)->getLogs($record),
|
||||||
'attributes' => new ComponentAttributeBag,
|
'attributes' => new ComponentAttributeBag,
|
||||||
]))
|
]))
|
||||||
->modalSubmitAction(false)
|
->modalSubmitAction(false)
|
||||||
@ -121,9 +130,9 @@ private function editAction(): Action
|
|||||||
|
|
||||||
return EditAction::make('edit')
|
return EditAction::make('edit')
|
||||||
->icon('heroicon-o-pencil-square')
|
->icon('heroicon-o-pencil-square')
|
||||||
->authorize(fn (Queue $record) => $user->can('update', [$record, $this->site, $this->site->server]))
|
->authorize(fn (Worker $record) => $user->can('update', [$record, $this->server, $this->site]))
|
||||||
->modalWidth(MaxWidth::ExtraLarge)
|
->modalWidth(MaxWidth::ExtraLarge)
|
||||||
->fillForm(fn (Queue $record): array => [
|
->fillForm(fn (Worker $record): array => [
|
||||||
'command' => $record->command,
|
'command' => $record->command,
|
||||||
'user' => $record->user,
|
'user' => $record->user,
|
||||||
'numprocs' => $record->numprocs,
|
'numprocs' => $record->numprocs,
|
||||||
@ -132,17 +141,17 @@ private function editAction(): Action
|
|||||||
])
|
])
|
||||||
->form([
|
->form([
|
||||||
TextInput::make('command')
|
TextInput::make('command')
|
||||||
->rules(EditQueue::rules($this->site->server)['command'])
|
->rules(EditWorker::rules($this->server, $this->site)['command'])
|
||||||
->helperText('Example: php /home/vito/your-site/artisan queue:work'),
|
->helperText('Example: php /home/vito/your-site/artisan queue:work'),
|
||||||
Select::make('user')
|
Select::make('user')
|
||||||
->rules(fn (callable $get) => EditQueue::rules($this->site->server)['user'])
|
->rules(fn (callable $get) => EditWorker::rules($this->server, $this->site)['user'])
|
||||||
->options([
|
->options([
|
||||||
'vito' => $this->site->server->ssh_user,
|
'vito' => $this->server->ssh_user,
|
||||||
'root' => 'root',
|
'root' => 'root',
|
||||||
]),
|
]),
|
||||||
TextInput::make('numprocs')
|
TextInput::make('numprocs')
|
||||||
->default(1)
|
->default(1)
|
||||||
->rules(EditQueue::rules($this->site->server)['numprocs'])
|
->rules(EditWorker::rules($this->server, $this->site)['numprocs'])
|
||||||
->helperText('Number of processes'),
|
->helperText('Number of processes'),
|
||||||
Grid::make()
|
Grid::make()
|
||||||
->schema([
|
->schema([
|
||||||
@ -152,9 +161,9 @@ private function editAction(): Action
|
|||||||
->default(false),
|
->default(false),
|
||||||
]),
|
]),
|
||||||
])
|
])
|
||||||
->using(function (Queue $record, array $data): void {
|
->using(function (Worker $record, array $data): void {
|
||||||
run_action($this, function () use ($record, $data): void {
|
run_action($this, function () use ($record, $data): void {
|
||||||
app(EditQueue::class)->edit($record, $data);
|
app(EditWorker::class)->edit($record, $data);
|
||||||
$this->dispatch('$refresh');
|
$this->dispatch('$refresh');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@ -167,10 +176,10 @@ private function deleteAction(): Action
|
|||||||
|
|
||||||
return DeleteAction::make('delete')
|
return DeleteAction::make('delete')
|
||||||
->icon('heroicon-o-trash')
|
->icon('heroicon-o-trash')
|
||||||
->authorize(fn (Queue $record) => $user->can('delete', [$record, $this->site, $this->site->server]))
|
->authorize(fn (Worker $record) => $user->can('delete', [$record, $this->server, $this->site]))
|
||||||
->using(function (Queue $record): void {
|
->using(function (Worker $record): void {
|
||||||
run_action($this, function () use ($record): void {
|
run_action($this, function () use ($record): void {
|
||||||
app(DeleteQueue::class)->delete($record);
|
app(DeleteWorker::class)->delete($record);
|
||||||
$this->dispatch('$refresh');
|
$this->dispatch('$refresh');
|
||||||
});
|
});
|
||||||
});
|
});
|
@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
use App\Enums\WorkerStatus;
|
||||||
use App\Models\Queue;
|
use App\Models\Worker;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends Factory<\App\Models\Queue>
|
* @extends Factory<Worker>
|
||||||
*/
|
*/
|
||||||
class QueueFactory extends Factory
|
class WorkerFactory extends Factory
|
||||||
{
|
{
|
||||||
protected $model = Queue::class;
|
protected $model = Worker::class;
|
||||||
|
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
@ -23,7 +23,7 @@ public function definition(): array
|
|||||||
'numprocs' => 1,
|
'numprocs' => 1,
|
||||||
'redirect_stderr' => 1,
|
'redirect_stderr' => 1,
|
||||||
'stdout_logfile' => 'file.log',
|
'stdout_logfile' => 'file.log',
|
||||||
'status' => QueueStatus::CREATING,
|
'status' => WorkerStatus::CREATING,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -0,0 +1,21 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::rename('queues', 'workers');
|
||||||
|
Schema::table('workers', function (Blueprint $table): void {
|
||||||
|
$table->unsignedInteger('site_id')->nullable()->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::rename('workers', 'queues');
|
||||||
|
}
|
||||||
|
};
|
@ -2,15 +2,15 @@
|
|||||||
|
|
||||||
namespace Database\Seeders;
|
namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
|
||||||
use App\Enums\SiteType;
|
use App\Enums\SiteType;
|
||||||
use App\Enums\SslStatus;
|
use App\Enums\SslStatus;
|
||||||
use App\Enums\SslType;
|
use App\Enums\SslType;
|
||||||
use App\Models\Queue;
|
use App\Enums\WorkerStatus;
|
||||||
use App\Models\Server;
|
use App\Models\Server;
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
use App\Models\SourceControl;
|
use App\Models\SourceControl;
|
||||||
use App\Models\Ssl;
|
use App\Models\Ssl;
|
||||||
|
use App\Models\Worker;
|
||||||
use Illuminate\Database\Eloquent\Builder;
|
use Illuminate\Database\Eloquent\Builder;
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
@ -36,10 +36,10 @@ public function run(): void
|
|||||||
'aliases' => ['www.'.$server->project->name.'.com'],
|
'aliases' => ['www.'.$server->project->name.'.com'],
|
||||||
]);
|
]);
|
||||||
$app->tags()->attach($server->tags()->first());
|
$app->tags()->attach($server->tags()->first());
|
||||||
Queue::factory()->create([
|
Worker::factory()->create([
|
||||||
'site_id' => $app->id,
|
'site_id' => $app->id,
|
||||||
'command' => 'php artisan queue:work',
|
'command' => 'php artisan queue:work',
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
Ssl::factory()->create([
|
Ssl::factory()->create([
|
||||||
'site_id' => $app->id,
|
'site_id' => $app->id,
|
||||||
|
@ -1 +0,0 @@
|
|||||||
<?php
|
|
@ -1 +0,0 @@
|
|||||||
<?php
|
|
@ -1 +0,0 @@
|
|||||||
<?php
|
|
@ -2,25 +2,25 @@
|
|||||||
|
|
||||||
namespace Tests\Feature;
|
namespace Tests\Feature;
|
||||||
|
|
||||||
use App\Enums\QueueStatus;
|
use App\Enums\WorkerStatus;
|
||||||
use App\Facades\SSH;
|
use App\Facades\SSH;
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Site;
|
use App\Models\Site;
|
||||||
use App\Web\Pages\Servers\Sites\Pages\Queues\Index;
|
use App\Models\Worker;
|
||||||
use App\Web\Pages\Servers\Sites\Pages\Queues\Widgets\QueuesList;
|
use App\Web\Pages\Servers\Sites\Pages\Workers\Index;
|
||||||
|
use App\Web\Pages\Servers\Sites\Pages\Workers\Widgets\WorkersList;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Livewire\Livewire;
|
use Livewire\Livewire;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
|
|
||||||
class QueuesTest extends TestCase
|
class WorkersTest extends TestCase
|
||||||
{
|
{
|
||||||
use RefreshDatabase;
|
use RefreshDatabase;
|
||||||
|
|
||||||
public function test_see_queues()
|
public function test_see_workers(): void
|
||||||
{
|
{
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
$queue = Queue::factory()->create([
|
$worker = Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
]);
|
]);
|
||||||
@ -32,33 +32,33 @@ public function test_see_queues()
|
|||||||
])
|
])
|
||||||
)
|
)
|
||||||
->assertSuccessful()
|
->assertSuccessful()
|
||||||
->assertSee($queue->command);
|
->assertSee($worker->command);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_delete_queue()
|
public function test_delete_worker(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
$queue = Queue::factory()->create([
|
$worker = Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(QueuesList::class, [
|
Livewire::test(WorkersList::class, [
|
||||||
'server' => $this->server,
|
'server' => $this->server,
|
||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
])
|
])
|
||||||
->callTableAction('delete', $queue->id)
|
->callTableAction('delete', $worker->id)
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseMissing('queues', [
|
$this->assertDatabaseMissing('workers', [
|
||||||
'id' => $queue->id,
|
'id' => $worker->id,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_create_queue()
|
public function test_create_worker(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
@ -69,7 +69,7 @@ public function test_create_queue()
|
|||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
])
|
])
|
||||||
->callAction('create', [
|
->callAction('create', [
|
||||||
'command' => 'php artisan queue:work',
|
'command' => 'php artisan worker:work',
|
||||||
'user' => 'vito',
|
'user' => 'vito',
|
||||||
'auto_start' => 1,
|
'auto_start' => 1,
|
||||||
'auto_restart' => 1,
|
'auto_restart' => 1,
|
||||||
@ -77,19 +77,19 @@ public function test_create_queue()
|
|||||||
])
|
])
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseHas('queues', [
|
$this->assertDatabaseHas('workers', [
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'command' => 'php artisan queue:work',
|
'command' => 'php artisan worker:work',
|
||||||
'user' => 'vito',
|
'user' => 'vito',
|
||||||
'auto_start' => 1,
|
'auto_start' => 1,
|
||||||
'auto_restart' => 1,
|
'auto_restart' => 1,
|
||||||
'numprocs' => 1,
|
'numprocs' => 1,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_create_queue_as_isolated_user(): void
|
public function test_create_worker_as_isolated_user(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ public function test_create_queue_as_isolated_user(): void
|
|||||||
])
|
])
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseHas('queues', [
|
$this->assertDatabaseHas('workers', [
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'command' => 'php artisan queue:work',
|
'command' => 'php artisan queue:work',
|
||||||
@ -119,11 +119,11 @@ public function test_create_queue_as_isolated_user(): void
|
|||||||
'auto_start' => 1,
|
'auto_start' => 1,
|
||||||
'auto_restart' => 1,
|
'auto_restart' => 1,
|
||||||
'numprocs' => 1,
|
'numprocs' => 1,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_cannot_create_queue_as_invalid_user(): void
|
public function test_cannot_create_worker_as_invalid_user(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
@ -142,14 +142,14 @@ public function test_cannot_create_queue_as_invalid_user(): void
|
|||||||
])
|
])
|
||||||
->assertHasActionErrors();
|
->assertHasActionErrors();
|
||||||
|
|
||||||
$this->assertDatabaseMissing('queues', [
|
$this->assertDatabaseMissing('workers', [
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'user' => 'example',
|
'user' => 'example',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_cannot_create_queue_on_another_sites_user(): void
|
public function test_cannot_create_worker_on_another_sites_user(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
@ -173,85 +173,85 @@ public function test_cannot_create_queue_on_another_sites_user(): void
|
|||||||
])
|
])
|
||||||
->assertHasActionErrors();
|
->assertHasActionErrors();
|
||||||
|
|
||||||
$this->assertDatabaseMissing('queues', [
|
$this->assertDatabaseMissing('workers', [
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'user' => 'example',
|
'user' => 'example',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_start_queue(): void
|
public function test_start_worker(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
$queue = Queue::factory()->create([
|
$worker = Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'status' => QueueStatus::STOPPED,
|
'status' => WorkerStatus::STOPPED,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(QueuesList::class, [
|
Livewire::test(WorkersList::class, [
|
||||||
'server' => $this->server,
|
'server' => $this->server,
|
||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
])
|
])
|
||||||
->callTableAction('start', $queue->id)
|
->callTableAction('start', $worker->id)
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseHas('queues', [
|
$this->assertDatabaseHas('workers', [
|
||||||
'id' => $queue->id,
|
'id' => $worker->id,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_stop_queue(): void
|
public function test_stop_worker(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
$queue = Queue::factory()->create([
|
$worker = Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(QueuesList::class, [
|
Livewire::test(WorkersList::class, [
|
||||||
'server' => $this->server,
|
'server' => $this->server,
|
||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
])
|
])
|
||||||
->callTableAction('stop', $queue->id)
|
->callTableAction('stop', $worker->id)
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseHas('queues', [
|
$this->assertDatabaseHas('workers', [
|
||||||
'id' => $queue->id,
|
'id' => $worker->id,
|
||||||
'status' => QueueStatus::STOPPED,
|
'status' => WorkerStatus::STOPPED,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function test_restart_queue(): void
|
public function test_restart_worker(): void
|
||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
$queue = Queue::factory()->create([
|
$worker = Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(QueuesList::class, [
|
Livewire::test(WorkersList::class, [
|
||||||
'server' => $this->server,
|
'server' => $this->server,
|
||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
])
|
])
|
||||||
->callTableAction('restart', $queue->id)
|
->callTableAction('restart', $worker->id)
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
|
|
||||||
$this->assertDatabaseHas('queues', [
|
$this->assertDatabaseHas('workers', [
|
||||||
'id' => $queue->id,
|
'id' => $worker->id,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,17 +261,17 @@ public function test_show_logs(): void
|
|||||||
|
|
||||||
$this->actingAs($this->user);
|
$this->actingAs($this->user);
|
||||||
|
|
||||||
$queue = Queue::factory()->create([
|
$worker = Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
'status' => QueueStatus::RUNNING,
|
'status' => WorkerStatus::RUNNING,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
Livewire::test(QueuesList::class, [
|
Livewire::test(WorkersList::class, [
|
||||||
'server' => $this->server,
|
'server' => $this->server,
|
||||||
'site' => $this->site,
|
'site' => $this->site,
|
||||||
])
|
])
|
||||||
->callTableAction('logs', $queue->id)
|
->callTableAction('logs', $worker->id)
|
||||||
->assertSuccessful();
|
->assertSuccessful();
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -6,8 +6,8 @@
|
|||||||
use App\Enums\ServiceStatus;
|
use App\Enums\ServiceStatus;
|
||||||
use App\Facades\SSH;
|
use App\Facades\SSH;
|
||||||
use App\Models\Database;
|
use App\Models\Database;
|
||||||
use App\Models\Queue;
|
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
use App\Models\Worker;
|
||||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
use Illuminate\Validation\ValidationException;
|
use Illuminate\Validation\ValidationException;
|
||||||
use Tests\TestCase;
|
use Tests\TestCase;
|
||||||
@ -74,7 +74,7 @@ public function test_cannot_uninstall_supervisor(): void
|
|||||||
{
|
{
|
||||||
SSH::fake();
|
SSH::fake();
|
||||||
|
|
||||||
Queue::factory()->create([
|
Worker::factory()->create([
|
||||||
'server_id' => $this->server->id,
|
'server_id' => $this->server->id,
|
||||||
'site_id' => $this->site->id,
|
'site_id' => $this->site->id,
|
||||||
]);
|
]);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user