mirror of
https://github.com/vitodeploy/vito.git
synced 2025-07-02 22:46:16 +00:00
refactoring (#116)
- refactoring architecture - fix incomplete ssh logs - code editor for scripts in the app - remove Jobs and SSHCommands
This commit is contained in:
@ -2,12 +2,9 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\BackupFileStatus;
|
||||
use App\Jobs\Backup\RunBackup;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
* @property string $type
|
||||
@ -71,16 +68,4 @@ public function files(): HasMany
|
||||
{
|
||||
return $this->hasMany(BackupFile::class, 'backup_id');
|
||||
}
|
||||
|
||||
public function run(): void
|
||||
{
|
||||
$file = new BackupFile([
|
||||
'backup_id' => $this->id,
|
||||
'name' => Str::of($this->database->name)->slug().'-'.now()->format('YmdHis'),
|
||||
'status' => BackupFileStatus::CREATING,
|
||||
]);
|
||||
$file->save();
|
||||
|
||||
dispatch(new RunBackup($file))->onConnection('ssh');
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\BackupFileStatus;
|
||||
use App\Jobs\Backup\RestoreDatabase;
|
||||
use App\Jobs\StorageProvider\DeleteFile;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -17,8 +14,6 @@
|
||||
* @property string $restored_to
|
||||
* @property Carbon $restored_at
|
||||
* @property Backup $backup
|
||||
* @property string $path
|
||||
* @property string $storage_path
|
||||
*/
|
||||
class BackupFile extends AbstractModel
|
||||
{
|
||||
@ -56,11 +51,12 @@ protected static function booted(): void
|
||||
}
|
||||
});
|
||||
|
||||
static::deleted(function (BackupFile $backupFile) {
|
||||
dispatch(new DeleteFile(
|
||||
$backupFile->backup->storage,
|
||||
[$backupFile->storage_path]
|
||||
));
|
||||
static::deleting(function (BackupFile $backupFile) {
|
||||
$provider = $backupFile->backup->storage->provider();
|
||||
$path = $backupFile->storagePath();
|
||||
dispatch(function () use ($provider, $path) {
|
||||
$provider->delete([$path]);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@ -69,21 +65,13 @@ public function backup(): BelongsTo
|
||||
return $this->belongsTo(Backup::class);
|
||||
}
|
||||
|
||||
public function getPathAttribute(): string
|
||||
public function path(): string
|
||||
{
|
||||
return '/home/'.$this->backup->server->ssh_user.'/'.$this->name.'.zip';
|
||||
return '/home/'.$this->backup->server->getSshUser().'/'.$this->name.'.zip';
|
||||
}
|
||||
|
||||
public function getStoragePathAttribute(): string
|
||||
public function storagePath(): string
|
||||
{
|
||||
return '/'.$this->name.'.zip';
|
||||
}
|
||||
|
||||
public function restore(Database $database): void
|
||||
{
|
||||
$this->status = BackupFileStatus::RESTORING;
|
||||
$this->restored_to = $database->name;
|
||||
$this->save();
|
||||
dispatch(new RestoreDatabase($this, $database))->onConnection('ssh');
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
* @property string $command
|
||||
* @property string $user
|
||||
* @property string $frequency
|
||||
* @property string $frequency_label
|
||||
* @property bool $hidden
|
||||
* @property string $status
|
||||
* @property string $crontab
|
||||
@ -34,10 +33,6 @@ class CronJob extends AbstractModel
|
||||
'hidden' => 'boolean',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'frequency_label',
|
||||
];
|
||||
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
@ -57,7 +52,7 @@ public static function crontab(Server $server, string $user): string
|
||||
return $data;
|
||||
}
|
||||
|
||||
public function getFrequencyLabelAttribute(): string
|
||||
public function frequencyLabel(): string
|
||||
{
|
||||
$labels = [
|
||||
'* * * * *' => 'Every minute',
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
@ -14,7 +13,6 @@
|
||||
* @property string $host
|
||||
* @property string $status
|
||||
* @property Server $server
|
||||
* @property string $full_user
|
||||
*/
|
||||
class DatabaseUser extends AbstractModel
|
||||
{
|
||||
@ -43,14 +41,4 @@ public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
public function scopeHasDatabase(Builder $query, string $databaseName): Builder
|
||||
{
|
||||
return $query->where('databases', 'like', "%\"$databaseName\"%");
|
||||
}
|
||||
|
||||
public function getFullUserAttribute(): string
|
||||
{
|
||||
return $this->username.'@'.$this->host;
|
||||
}
|
||||
}
|
||||
|
@ -37,10 +37,6 @@ class Deployment extends AbstractModel
|
||||
'commit_data' => 'json',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'commit_id_short',
|
||||
];
|
||||
|
||||
public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
@ -55,13 +51,4 @@ public function log(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(ServerLog::class, 'log_id');
|
||||
}
|
||||
|
||||
public function getCommitIdShortAttribute(): string
|
||||
{
|
||||
if ($this->commit_id) {
|
||||
return substr($this->commit_id, 0, 7);
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
* @property int $server_id
|
||||
* @property string $type
|
||||
* @property string $protocol
|
||||
* @property string $real_protocol
|
||||
* @property int $port
|
||||
* @property string $source
|
||||
* @property ?string $mask
|
||||
@ -37,16 +36,12 @@ class FirewallRule extends AbstractModel
|
||||
'port' => 'integer',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'real_protocol',
|
||||
];
|
||||
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
public function getRealProtocolAttribute(): string
|
||||
public function getRealProtocol(): string
|
||||
{
|
||||
return $this->protocol === 'udp' ? 'udp' : 'tcp';
|
||||
}
|
||||
|
@ -2,12 +2,8 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @property int $site_id
|
||||
@ -52,11 +48,6 @@ public function sourceControl(): BelongsTo
|
||||
return $this->belongsTo(SourceControl::class);
|
||||
}
|
||||
|
||||
public function scopeHasEvent(Builder $query, string $event): Builder
|
||||
{
|
||||
return $query->where('events', 'like', "%\"{$event}\"%");
|
||||
}
|
||||
|
||||
public function deployHook(): void
|
||||
{
|
||||
$this->update(
|
||||
@ -64,19 +55,9 @@ public function deployHook(): void
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function destroyHook(): void
|
||||
{
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$this->sourceControl->provider()->destroyHook($this->site->repository, $this->hook_id);
|
||||
$this->delete();
|
||||
DB::commit();
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
throw $e;
|
||||
}
|
||||
$this->sourceControl->provider()->destroyHook($this->site->repository, $this->hook_id);
|
||||
$this->delete();
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\Notification;
|
||||
use App\Notifications\NotificationInterface;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
@ -33,14 +33,14 @@ class NotificationChannel extends AbstractModel
|
||||
'is_default' => 'boolean',
|
||||
];
|
||||
|
||||
public function provider(): \App\Contracts\NotificationChannel
|
||||
public function provider(): \App\NotificationChannels\NotificationChannel
|
||||
{
|
||||
$class = config('core.notification_channels_providers_class')[$this->provider];
|
||||
|
||||
return new $class($this);
|
||||
}
|
||||
|
||||
public static function notifyAll(Notification $notification): void
|
||||
public static function notifyAll(NotificationInterface $notification): void
|
||||
{
|
||||
$channels = self::all();
|
||||
foreach ($channels as $channel) {
|
||||
|
@ -2,11 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\QueueStatus;
|
||||
use App\Jobs\Queue\Deploy;
|
||||
use App\Jobs\Queue\GetLogs;
|
||||
use App\Jobs\Queue\Manage;
|
||||
use App\Jobs\Queue\Remove;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
@ -21,8 +16,6 @@
|
||||
* @property int $redirect_stderr
|
||||
* @property string $stdout_logfile
|
||||
* @property string $status
|
||||
* @property string $log_directory
|
||||
* @property string $log_file
|
||||
* @property Server $server
|
||||
* @property Site $site
|
||||
*/
|
||||
@ -73,71 +66,13 @@ public function site(): BelongsTo
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
public function getLogDirectoryAttribute(): string
|
||||
public function getLogDirectory(): string
|
||||
{
|
||||
return '/home/'.$this->user.'/.logs/workers';
|
||||
}
|
||||
|
||||
public function getLogFileAttribute(): string
|
||||
public function getLogFile(): string
|
||||
{
|
||||
return $this->log_directory.'/'.$this->id.'.log';
|
||||
}
|
||||
|
||||
public function deploy(): void
|
||||
{
|
||||
dispatch(new Deploy($this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
private function action(string $type, string $status, string $successStatus, string $failStatus, string $failMessage): void
|
||||
{
|
||||
$this->status = $status;
|
||||
$this->save();
|
||||
dispatch(new Manage($this, $type, $successStatus, $failStatus, $failMessage))
|
||||
->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function start(): void
|
||||
{
|
||||
$this->action(
|
||||
'start',
|
||||
QueueStatus::STARTING,
|
||||
QueueStatus::RUNNING,
|
||||
QueueStatus::FAILED,
|
||||
__('Failed to start')
|
||||
);
|
||||
}
|
||||
|
||||
public function stop(): void
|
||||
{
|
||||
$this->action(
|
||||
'stop',
|
||||
QueueStatus::STOPPING,
|
||||
QueueStatus::STOPPED,
|
||||
QueueStatus::FAILED,
|
||||
__('Failed to stop')
|
||||
);
|
||||
}
|
||||
|
||||
public function restart(): void
|
||||
{
|
||||
$this->action(
|
||||
'restart',
|
||||
QueueStatus::RESTARTING,
|
||||
QueueStatus::RUNNING,
|
||||
QueueStatus::FAILED,
|
||||
__('Failed to restart')
|
||||
);
|
||||
}
|
||||
|
||||
public function remove(): void
|
||||
{
|
||||
$this->status = QueueStatus::DELETING;
|
||||
$this->save();
|
||||
dispatch(new Remove($this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function getLogs(): void
|
||||
{
|
||||
dispatch(new GetLogs($this))->onConnection('ssh');
|
||||
return $this->getLogDirectory().'/'.$this->id.'.log';
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Jobs\Redirect\AddToServer;
|
||||
use App\Jobs\Redirect\DeleteFromServer;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
|
||||
@ -35,16 +33,4 @@ public function site(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
public function addToServer(): void
|
||||
{
|
||||
dispatch(new AddToServer($this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function deleteFromServer(): void
|
||||
{
|
||||
$this->status = 'deleting';
|
||||
$this->save();
|
||||
dispatch(new DeleteFromServer($this))->onConnection('ssh');
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Jobs\Script\ExecuteOn;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
@ -36,9 +35,4 @@ public function executions(): HasMany
|
||||
{
|
||||
return $this->hasMany(ScriptExecution::class, 'script_id');
|
||||
}
|
||||
|
||||
public function executeOn(Server $server, string $user): void
|
||||
{
|
||||
dispatch(new ExecuteOn($this, $server, $user))->onConnection('ssh');
|
||||
}
|
||||
}
|
||||
|
@ -3,15 +3,12 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Actions\Server\CheckConnection;
|
||||
use App\Actions\Server\RebootServer;
|
||||
use App\Contracts\ServerType;
|
||||
use App\Enums\ServerStatus;
|
||||
use App\Enums\ServiceStatus;
|
||||
use App\Facades\Notifier;
|
||||
use App\Facades\SSH;
|
||||
use App\Jobs\Installation\Upgrade;
|
||||
use App\Notifications\ServerInstallationStarted;
|
||||
use App\Support\Testing\SSHFake;
|
||||
use App\ServerTypes\ServerType;
|
||||
use App\SSH\Cron\Cron;
|
||||
use App\SSH\OS\OS;
|
||||
use App\SSH\Systemd\Systemd;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@ -205,6 +202,22 @@ public function daemons(): HasMany
|
||||
return $this->queues()->whereNull('site_id');
|
||||
}
|
||||
|
||||
public function sshKeys(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(SshKey::class, 'server_ssh_keys')
|
||||
->withPivot('status')
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
public function getSshUser(): string
|
||||
{
|
||||
if ($this->ssh_user) {
|
||||
return $this->ssh_user;
|
||||
}
|
||||
|
||||
return config('core.ssh_user');
|
||||
}
|
||||
|
||||
public function service($type, $version = null): ?Service
|
||||
{
|
||||
/* @var Service $service */
|
||||
@ -230,6 +243,7 @@ public function defaultService($type): ?Service
|
||||
|
||||
// If no default service found, get the first service with status ready or stopped
|
||||
if (! $service) {
|
||||
/** @var Service $service */
|
||||
$service = $this->services()
|
||||
->where('type', $type)
|
||||
->whereIn('status', [ServiceStatus::READY, ServiceStatus::STOPPED])
|
||||
@ -243,24 +257,7 @@ public function defaultService($type): ?Service
|
||||
return $service;
|
||||
}
|
||||
|
||||
public function getServiceByUnit($unit): ?Service
|
||||
{
|
||||
/* @var Service $service */
|
||||
$service = $this->services()
|
||||
->where('unit', $unit)
|
||||
->where('is_default', 1)
|
||||
->first();
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
public function install(): void
|
||||
{
|
||||
$this->type()->install();
|
||||
Notifier::send($this, new ServerInstallationStarted($this));
|
||||
}
|
||||
|
||||
public function ssh(?string $user = null): \App\Helpers\SSH|SSHFake
|
||||
public function ssh(?string $user = null): mixed
|
||||
{
|
||||
return SSH::init($this, $user);
|
||||
}
|
||||
@ -283,7 +280,7 @@ public function type(): ServerType
|
||||
return new $typeClass($this);
|
||||
}
|
||||
|
||||
public function provider(): \App\Contracts\ServerProvider
|
||||
public function provider(): \App\ServerProviders\ServerProvider
|
||||
{
|
||||
$providerClass = config('core.server_providers_class')[$this->provider];
|
||||
|
||||
@ -335,32 +332,8 @@ public function php(?string $version = null): ?Service
|
||||
return $this->service('php', $version);
|
||||
}
|
||||
|
||||
public function sshKeys(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(SshKey::class, 'server_ssh_keys')
|
||||
->withPivot('status')
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
public function getSshUserAttribute(string $value): string
|
||||
{
|
||||
if ($value) {
|
||||
return $value;
|
||||
}
|
||||
|
||||
return config('core.ssh_user');
|
||||
}
|
||||
|
||||
public function sshKey(): array
|
||||
{
|
||||
if (app()->environment() == 'testing') {
|
||||
return [
|
||||
'public_key' => 'public',
|
||||
'public_key_path' => '/path',
|
||||
'private_key_path' => '/path',
|
||||
];
|
||||
}
|
||||
|
||||
/** @var FilesystemAdapter $storageDisk */
|
||||
$storageDisk = Storage::disk(config('core.key_pairs_disk'));
|
||||
|
||||
@ -371,44 +344,28 @@ public function sshKey(): array
|
||||
];
|
||||
}
|
||||
|
||||
public function getServiceUnits(): array
|
||||
{
|
||||
$units = [];
|
||||
$services = $this->services;
|
||||
foreach ($services as $service) {
|
||||
if ($service->unit) {
|
||||
$units[] = $service->unit;
|
||||
}
|
||||
}
|
||||
|
||||
return $units;
|
||||
}
|
||||
|
||||
public function checkConnection(): self
|
||||
{
|
||||
return app(CheckConnection::class)->check($this);
|
||||
}
|
||||
|
||||
public function installUpdates(): void
|
||||
{
|
||||
$this->available_updates = 0;
|
||||
$this->security_updates = 0;
|
||||
$this->save();
|
||||
dispatch(new Upgrade($this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function reboot(): self
|
||||
{
|
||||
return app(RebootServer::class)->reboot($this);
|
||||
}
|
||||
|
||||
public function getHostnameAttribute(): string
|
||||
public function hostname(): string
|
||||
{
|
||||
return Str::of($this->name)->slug();
|
||||
}
|
||||
|
||||
public function isReady(): bool
|
||||
public function os(): OS
|
||||
{
|
||||
return $this->status == ServerStatus::READY;
|
||||
return new OS($this);
|
||||
}
|
||||
|
||||
public function systemd(): Systemd
|
||||
{
|
||||
return new Systemd($this);
|
||||
}
|
||||
|
||||
public function cron(): Cron
|
||||
{
|
||||
return new Cron($this);
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,6 @@
|
||||
* @property string $disk
|
||||
* @property Server $server
|
||||
* @property ?Site $site
|
||||
* @property string $content
|
||||
*/
|
||||
class ServerLog extends AbstractModel
|
||||
{
|
||||
@ -72,7 +71,7 @@ public function write($buf): void
|
||||
}
|
||||
}
|
||||
|
||||
public function getContentAttribute(): ?string
|
||||
public function getContent(): ?string
|
||||
{
|
||||
if (Storage::disk($this->disk)->exists($this->name)) {
|
||||
return Storage::disk($this->disk)->get($this->name);
|
||||
@ -80,4 +79,17 @@ public function getContentAttribute(): ?string
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public static function log(Server $server, string $type, string $content, ?Site $site = null): void
|
||||
{
|
||||
$log = new static([
|
||||
'server_id' => $server->id,
|
||||
'site_id' => $site?->id,
|
||||
'name' => $server->id.'-'.strtotime('now').'-'.$type.'.log',
|
||||
'type' => $type,
|
||||
'disk' => config('core.logs_disk'),
|
||||
]);
|
||||
$log->save();
|
||||
$log->write($content);
|
||||
}
|
||||
}
|
||||
|
@ -2,17 +2,16 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\Database;
|
||||
use App\Contracts\Firewall;
|
||||
use App\Contracts\ProcessManager;
|
||||
use App\Contracts\Webserver;
|
||||
use App\Enums\ServiceStatus;
|
||||
use App\Exceptions\InstallationFailed;
|
||||
use App\Jobs\Service\Manage;
|
||||
use App\ServiceHandlers\PHP;
|
||||
use App\Actions\Service\Manage;
|
||||
use App\Exceptions\ServiceInstallationFailed;
|
||||
use App\SSH\Services\Database\Database as DatabaseHandler;
|
||||
use App\SSH\Services\Firewall\Firewall as FirewallHandler;
|
||||
use App\SSH\Services\PHP\PHP as PHPHandler;
|
||||
use App\SSH\Services\ProcessManager\ProcessManager as ProcessManagerHandler;
|
||||
use App\SSH\Services\Redis\Redis as RedisHandler;
|
||||
use App\SSH\Services\Webserver\Webserver as WebserverHandler;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Support\Facades\Bus;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
/**
|
||||
@ -49,134 +48,49 @@ class Service extends AbstractModel
|
||||
'is_default' => 'boolean',
|
||||
];
|
||||
|
||||
public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
|
||||
static::creating(function (Service $service) {
|
||||
$service->unit = config('core.service_units')[$service->name][$service->server->os][$service->version];
|
||||
});
|
||||
}
|
||||
|
||||
public function server(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
public function handler(): Database|Firewall|Webserver|PHP|ProcessManager
|
||||
{
|
||||
public function handler(
|
||||
): PHPHandler|WebserverHandler|DatabaseHandler|FirewallHandler|ProcessManagerHandler|RedisHandler {
|
||||
$handler = config('core.service_handlers')[$this->name];
|
||||
|
||||
return new $handler($this);
|
||||
}
|
||||
|
||||
public function installer(): mixed
|
||||
{
|
||||
$installer = config('core.service_installers')[$this->name];
|
||||
|
||||
return new $installer($this);
|
||||
}
|
||||
|
||||
public function uninstaller(): mixed
|
||||
{
|
||||
$uninstaller = config('core.service_uninstallers')[$this->name];
|
||||
|
||||
return new $uninstaller($this);
|
||||
}
|
||||
|
||||
public function getUnitAttribute($value): ?string
|
||||
{
|
||||
if ($value) {
|
||||
return $value;
|
||||
}
|
||||
if (isset(config('core.service_units')[$this->name])) {
|
||||
$value = config('core.service_units')[$this->name][$this->server->os][$this->version];
|
||||
if ($value) {
|
||||
$this->fill(['unit' => $value]);
|
||||
$this->save();
|
||||
}
|
||||
}
|
||||
|
||||
return $value;
|
||||
}
|
||||
|
||||
public function install(): void
|
||||
{
|
||||
Bus::chain([
|
||||
$this->installer(),
|
||||
])->onConnection('ssh-long')->dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws InstallationFailed
|
||||
* @throws ServiceInstallationFailed
|
||||
*/
|
||||
public function validateInstall($result): void
|
||||
{
|
||||
if (! Str::contains($result, 'Active: active')) {
|
||||
throw new InstallationFailed();
|
||||
throw new ServiceInstallationFailed();
|
||||
}
|
||||
}
|
||||
|
||||
public function uninstall(): void
|
||||
{
|
||||
$this->status = ServiceStatus::UNINSTALLING;
|
||||
$this->save();
|
||||
Bus::chain([
|
||||
$this->uninstaller(),
|
||||
function () {
|
||||
$this->delete();
|
||||
},
|
||||
])->catch(function () {
|
||||
$this->status = ServiceStatus::FAILED;
|
||||
$this->save();
|
||||
})->onConnection('ssh')->dispatch();
|
||||
}
|
||||
|
||||
public function start(): void
|
||||
{
|
||||
$this->action(
|
||||
'start',
|
||||
ServiceStatus::STARTING,
|
||||
ServiceStatus::READY,
|
||||
ServiceStatus::STOPPED,
|
||||
__('Failed to start')
|
||||
);
|
||||
app(Manage::class)->start($this);
|
||||
}
|
||||
|
||||
public function stop(): void
|
||||
{
|
||||
$this->action(
|
||||
'stop',
|
||||
ServiceStatus::STOPPING,
|
||||
ServiceStatus::STOPPED,
|
||||
ServiceStatus::FAILED,
|
||||
__('Failed to stop')
|
||||
);
|
||||
app(Manage::class)->stop($this);
|
||||
}
|
||||
|
||||
public function restart(): void
|
||||
{
|
||||
$this->action(
|
||||
'restart',
|
||||
ServiceStatus::RESTARTING,
|
||||
ServiceStatus::READY,
|
||||
ServiceStatus::FAILED,
|
||||
__('Failed to restart')
|
||||
);
|
||||
}
|
||||
|
||||
public function action(
|
||||
string $type,
|
||||
string $status,
|
||||
string $successStatus,
|
||||
string $failStatus,
|
||||
string $failMessage
|
||||
): void {
|
||||
$this->status = $status;
|
||||
$this->save();
|
||||
dispatch(new Manage($this, $type, $successStatus, $failStatus, $failMessage))
|
||||
->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function installedVersions(): array
|
||||
{
|
||||
$versions = [];
|
||||
$services = $this->server->services()->where('type', $this->type)->get(['version']);
|
||||
foreach ($services as $service) {
|
||||
$versions[] = $service->version;
|
||||
}
|
||||
|
||||
return $versions;
|
||||
app(Manage::class)->restart($this);
|
||||
}
|
||||
}
|
||||
|
@ -2,27 +2,14 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\SiteType;
|
||||
use App\Enums\DeploymentStatus;
|
||||
use App\Enums\SiteStatus;
|
||||
use App\Enums\SslStatus;
|
||||
use App\Exceptions\SourceControlIsNotConnected;
|
||||
use App\Facades\Notifier;
|
||||
use App\Jobs\Site\Deploy;
|
||||
use App\Jobs\Site\UpdateBranch;
|
||||
use App\Notifications\SiteInstallationFailed;
|
||||
use App\Notifications\SiteInstallationSucceed;
|
||||
use App\SSHCommands\Website\GetEnvCommand;
|
||||
use Exception;
|
||||
use App\SiteTypes\SiteType;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
use Illuminate\Database\Eloquent\Relations\HasOne;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Str;
|
||||
use Throwable;
|
||||
|
||||
/**
|
||||
* @property int $server_id
|
||||
@ -31,7 +18,6 @@
|
||||
* @property string $domain
|
||||
* @property array $aliases
|
||||
* @property string $web_directory
|
||||
* @property string $web_directory_path
|
||||
* @property string $path
|
||||
* @property string $php_version
|
||||
* @property string $source_control
|
||||
@ -42,8 +28,6 @@
|
||||
* @property string $status
|
||||
* @property int $port
|
||||
* @property int $progress
|
||||
* @property bool $auto_deployment
|
||||
* @property string $url
|
||||
* @property Server $server
|
||||
* @property ServerLog[] $logs
|
||||
* @property Deployment[] $deployments
|
||||
@ -53,10 +37,6 @@
|
||||
* @property Queue[] $queues
|
||||
* @property Ssl[] $ssls
|
||||
* @property ?Ssl $activeSsl
|
||||
* @property string $full_repository_url
|
||||
* @property string $aliases_string
|
||||
* @property string $deployment_script_text
|
||||
* @property string $env
|
||||
* @property string $ssh_key_name
|
||||
*/
|
||||
class Site extends AbstractModel
|
||||
@ -87,16 +67,10 @@ class Site extends AbstractModel
|
||||
'type_data' => 'json',
|
||||
'port' => 'integer',
|
||||
'progress' => 'integer',
|
||||
'auto_deployment' => 'boolean',
|
||||
'aliases' => 'array',
|
||||
'source_control_id' => 'integer',
|
||||
];
|
||||
|
||||
protected $appends = [
|
||||
'url',
|
||||
'auto_deployment',
|
||||
];
|
||||
|
||||
public static function boot(): void
|
||||
{
|
||||
parent::boot();
|
||||
@ -186,12 +160,12 @@ public function sourceControl(): SourceControl|HasOne|null|Model
|
||||
/**
|
||||
* @throws SourceControlIsNotConnected
|
||||
*/
|
||||
public function getFullRepositoryUrlAttribute()
|
||||
public function getFullRepositoryUrl()
|
||||
{
|
||||
return $this->sourceControl()->provider()->fullRepoUrl($this->repository, $this->ssh_key_name);
|
||||
return $this->sourceControl()->provider()->fullRepoUrl($this->repository, $this->getSshKeyName());
|
||||
}
|
||||
|
||||
public function getAliasesStringAttribute(): string
|
||||
public function getAliasesString(): string
|
||||
{
|
||||
if (count($this->aliases) > 0) {
|
||||
return implode(' ', $this->aliases);
|
||||
@ -207,19 +181,6 @@ public function type(): SiteType
|
||||
return new $typeClass($this);
|
||||
}
|
||||
|
||||
public function install(): void
|
||||
{
|
||||
$this->type()->install();
|
||||
}
|
||||
|
||||
public function remove(): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => SiteStatus::DELETING,
|
||||
]);
|
||||
$this->type()->delete();
|
||||
}
|
||||
|
||||
public function php(): ?Service
|
||||
{
|
||||
if ($this->php_version) {
|
||||
@ -233,57 +194,7 @@ public function changePHPVersion($version): void
|
||||
{
|
||||
$this->php_version = $version;
|
||||
$this->server->webserver()->handler()->changePHPVersion($this, $version);
|
||||
}
|
||||
|
||||
public function getDeploymentScriptTextAttribute(): string
|
||||
{
|
||||
/* @var DeploymentScript $script */
|
||||
$script = $this->deploymentScript()->firstOrCreate([
|
||||
'site_id' => $this->id,
|
||||
], [
|
||||
'site_id' => $this->id,
|
||||
'name' => 'default',
|
||||
]);
|
||||
|
||||
return $script->content;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws SourceControlIsNotConnected
|
||||
*/
|
||||
public function deploy(): Deployment
|
||||
{
|
||||
if ($this->sourceControl()) {
|
||||
$this->sourceControl()->getRepo($this->repository);
|
||||
}
|
||||
|
||||
$deployment = new Deployment([
|
||||
'site_id' => $this->id,
|
||||
'deployment_script_id' => $this->deploymentScript->id,
|
||||
'status' => DeploymentStatus::DEPLOYING,
|
||||
]);
|
||||
$lastCommit = $this->sourceControl()->provider()->getLastCommit($this->repository, $this->branch);
|
||||
if ($lastCommit) {
|
||||
$deployment->commit_id = $lastCommit['commit_id'];
|
||||
$deployment->commit_data = $lastCommit['commit_data'];
|
||||
}
|
||||
$deployment->save();
|
||||
|
||||
dispatch(new Deploy($deployment, $this->path))->onConnection('ssh');
|
||||
|
||||
return $deployment;
|
||||
}
|
||||
|
||||
public function getEnvAttribute(): string
|
||||
{
|
||||
$typeData = $this->type_data;
|
||||
if (! isset($typeData['env'])) {
|
||||
$typeData['env'] = '';
|
||||
$this->type_data = $typeData;
|
||||
$this->save();
|
||||
}
|
||||
|
||||
return $typeData['env'];
|
||||
$this->save();
|
||||
}
|
||||
|
||||
public function activeSsl(): HasOne
|
||||
@ -293,33 +204,7 @@ public function activeSsl(): HasOne
|
||||
->orderByDesc('id');
|
||||
}
|
||||
|
||||
public function createFreeSsl(): void
|
||||
{
|
||||
$ssl = new Ssl([
|
||||
'site_id' => $this->id,
|
||||
'type' => 'letsencrypt',
|
||||
'expires_at' => now()->addMonths(3),
|
||||
'status' => SslStatus::CREATING,
|
||||
]);
|
||||
$ssl->save();
|
||||
$ssl->deploy();
|
||||
}
|
||||
|
||||
public function createCustomSsl(string $certificate, string $pk): void
|
||||
{
|
||||
$ssl = new Ssl([
|
||||
'site_id' => $this->id,
|
||||
'type' => 'custom',
|
||||
'certificate' => $certificate,
|
||||
'pk' => $pk,
|
||||
'expires_at' => '',
|
||||
'status' => SslStatus::CREATING,
|
||||
]);
|
||||
$ssl->save();
|
||||
$ssl->deploy();
|
||||
}
|
||||
|
||||
public function getUrlAttribute(): string
|
||||
public function getUrl(): string
|
||||
{
|
||||
if ($this->activeSsl) {
|
||||
return 'https://'.$this->domain;
|
||||
@ -328,7 +213,7 @@ public function getUrlAttribute(): string
|
||||
return 'http://'.$this->domain;
|
||||
}
|
||||
|
||||
public function getWebDirectoryPathAttribute(): string
|
||||
public function getWebDirectoryPath(): string
|
||||
{
|
||||
if ($this->web_directory) {
|
||||
return $this->path.'/'.$this->web_directory;
|
||||
@ -339,7 +224,6 @@ public function getWebDirectoryPathAttribute(): string
|
||||
|
||||
/**
|
||||
* @throws SourceControlIsNotConnected
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function enableAutoDeployment(): void
|
||||
{
|
||||
@ -347,92 +231,50 @@ public function enableAutoDeployment(): void
|
||||
return;
|
||||
}
|
||||
|
||||
if (! $this->sourceControl()) {
|
||||
if (! $this->sourceControl()?->getRepo($this->repository)) {
|
||||
throw new SourceControlIsNotConnected($this->source_control);
|
||||
}
|
||||
|
||||
DB::beginTransaction();
|
||||
try {
|
||||
$gitHook = new GitHook([
|
||||
'site_id' => $this->id,
|
||||
'source_control_id' => $this->sourceControl()->id,
|
||||
'secret' => Str::uuid()->toString(),
|
||||
'actions' => ['deploy'],
|
||||
'events' => ['push'],
|
||||
]);
|
||||
$gitHook->save();
|
||||
$gitHook->deployHook();
|
||||
DB::commit();
|
||||
} catch (Exception $e) {
|
||||
DB::rollBack();
|
||||
throw $e;
|
||||
}
|
||||
$gitHook = new GitHook([
|
||||
'site_id' => $this->id,
|
||||
'source_control_id' => $this->sourceControl()->id,
|
||||
'secret' => Str::uuid()->toString(),
|
||||
'actions' => ['deploy'],
|
||||
'events' => ['push'],
|
||||
]);
|
||||
$gitHook->save();
|
||||
$gitHook->deployHook();
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
* @throws SourceControlIsNotConnected
|
||||
*/
|
||||
public function disableAutoDeployment(): void
|
||||
{
|
||||
if (! $this->sourceControl()?->getRepo($this->repository)) {
|
||||
throw new SourceControlIsNotConnected($this->source_control);
|
||||
}
|
||||
|
||||
$this->gitHook?->destroyHook();
|
||||
}
|
||||
|
||||
public function getAutoDeploymentAttribute(): bool
|
||||
public function isAutoDeployment(): bool
|
||||
{
|
||||
return (bool) $this->gitHook;
|
||||
}
|
||||
|
||||
public function updateBranch(string $branch): void
|
||||
{
|
||||
dispatch(new UpdateBranch($this, $branch))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function getSshKeyNameAttribute(): string
|
||||
public function getSshKeyName(): string
|
||||
{
|
||||
return str('site_'.$this->id)->toString();
|
||||
}
|
||||
|
||||
public function installationFinished(): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => SiteStatus::READY,
|
||||
'progress' => 100,
|
||||
]);
|
||||
Notifier::send($this, new SiteInstallationSucceed($this));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Throwable
|
||||
*/
|
||||
public function installationFailed(Throwable $e): void
|
||||
{
|
||||
$this->update([
|
||||
'status' => SiteStatus::INSTALLATION_FAILED,
|
||||
]);
|
||||
Notifier::send($this, new SiteInstallationFailed($this));
|
||||
Log::error('install-site-error', [
|
||||
'error' => (string) $e,
|
||||
]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
|
||||
public function hasFeature(string $feature): bool
|
||||
{
|
||||
return in_array($feature, $this->type()->supportedFeatures());
|
||||
}
|
||||
|
||||
public function isReady(): bool
|
||||
{
|
||||
return $this->status === SiteStatus::READY;
|
||||
}
|
||||
|
||||
public function getEnv(): string
|
||||
{
|
||||
return $this->server->ssh()->exec(
|
||||
new GetEnvCommand(
|
||||
$this->domain
|
||||
)
|
||||
);
|
||||
return $this->server->os()->readFile($this->path.'/.env');
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Contracts\SourceControlProvider;
|
||||
use App\SourceControlProviders\SourceControlProvider;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
|
||||
/**
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\SshKeyStatus;
|
||||
use App\Jobs\SshKey\DeleteSshKeyFromServer;
|
||||
use App\Jobs\SshKey\DeploySshKeyToServer;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||
@ -47,20 +44,4 @@ public function existsOnServer(Server $server): bool
|
||||
{
|
||||
return (bool) $this->servers()->where('id', $server->id)->first();
|
||||
}
|
||||
|
||||
public function deployTo(Server $server): void
|
||||
{
|
||||
$server->sshKeys()->attach($this, [
|
||||
'status' => SshKeyStatus::ADDING,
|
||||
]);
|
||||
dispatch(new DeploySshKeyToServer($server, $this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function deleteFrom(Server $server): void
|
||||
{
|
||||
$this->servers()->updateExistingPivot($server->id, [
|
||||
'status' => SshKeyStatus::DELETING,
|
||||
]);
|
||||
dispatch(new DeleteSshKeyFromServer($server, $this))->onConnection('ssh');
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,6 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\SslStatus;
|
||||
use App\Jobs\Ssl\Deploy;
|
||||
use App\Jobs\Ssl\Remove;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\BelongsTo;
|
||||
@ -19,9 +16,6 @@
|
||||
* @property Carbon $expires_at
|
||||
* @property string $status
|
||||
* @property Site $site
|
||||
* @property string $certs_directory_path
|
||||
* @property string $certificate_path
|
||||
* @property string $pk_path
|
||||
* @property string $ca_path
|
||||
*/
|
||||
class Ssl extends AbstractModel
|
||||
@ -51,7 +45,7 @@ public function site(): BelongsTo
|
||||
return $this->belongsTo(Site::class);
|
||||
}
|
||||
|
||||
public function getCertsDirectoryPathAttribute(): ?string
|
||||
public function getCertsDirectoryPath(): ?string
|
||||
{
|
||||
if ($this->type == 'letsencrypt') {
|
||||
return '/etc/letsencrypt/live/'.$this->site->domain;
|
||||
@ -64,57 +58,45 @@ public function getCertsDirectoryPathAttribute(): ?string
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getCertificatePathAttribute(): ?string
|
||||
public function getCertificatePath(): ?string
|
||||
{
|
||||
if ($this->type == 'letsencrypt') {
|
||||
return $this->certificate;
|
||||
}
|
||||
|
||||
if ($this->type == 'custom') {
|
||||
return $this->certs_directory_path.'/cert.pem';
|
||||
return $this->getCertsDirectoryPath().'/cert.pem';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getPkPathAttribute(): ?string
|
||||
public function getPkPath(): ?string
|
||||
{
|
||||
if ($this->type == 'letsencrypt') {
|
||||
return $this->pk;
|
||||
}
|
||||
|
||||
if ($this->type == 'custom') {
|
||||
return $this->certs_directory_path.'/privkey.pem';
|
||||
return $this->getCertsDirectoryPath().'/privkey.pem';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function getCaPathAttribute(): ?string
|
||||
public function getCaPath(): ?string
|
||||
{
|
||||
if ($this->type == 'letsencrypt') {
|
||||
return $this->ca;
|
||||
}
|
||||
|
||||
if ($this->type == 'custom') {
|
||||
return $this->certs_directory_path.'/fullchain.pem';
|
||||
return $this->getCertsDirectoryPath().'/fullchain.pem';
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
public function deploy(): void
|
||||
{
|
||||
dispatch(new Deploy($this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function remove(): void
|
||||
{
|
||||
$this->status = SslStatus::DELETING;
|
||||
$this->save();
|
||||
dispatch(new Remove($this))->onConnection('ssh');
|
||||
}
|
||||
|
||||
public function validateSetup(string $result): bool
|
||||
{
|
||||
if (! Str::contains($result, 'Successfully received certificate')) {
|
||||
@ -122,8 +104,8 @@ public function validateSetup(string $result): bool
|
||||
}
|
||||
|
||||
if ($this->type == 'letsencrypt') {
|
||||
$this->certificate = $this->certs_directory_path.'/fullchain.pem';
|
||||
$this->pk = $this->certs_directory_path.'/privkey.pem';
|
||||
$this->certificate = $this->getCertsDirectoryPath().'/fullchain.pem';
|
||||
$this->pk = $this->getCertsDirectoryPath().'/privkey.pem';
|
||||
$this->save();
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ public function user(): BelongsTo
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
public function provider(): \App\Contracts\StorageProvider
|
||||
public function provider(): \App\StorageProviders\StorageProvider
|
||||
{
|
||||
$providerClass = config('core.storage_providers_class')[$this->provider];
|
||||
|
||||
|
Reference in New Issue
Block a user