diff --git a/app/Actions/Service/Manage.php b/app/Actions/Service/Manage.php index a7a9a90..18010a3 100644 --- a/app/Actions/Service/Manage.php +++ b/app/Actions/Service/Manage.php @@ -51,4 +51,34 @@ public function restart(Service $service): void $service->save(); })->onConnection('ssh'); } + + public function enable(Service $service): void + { + $service->status = ServiceStatus::ENABLING; + $service->save(); + dispatch(function () use ($service) { + $status = $service->server->systemd()->enable($service->unit); + if (str($status)->contains('Active: active')) { + $service->status = ServiceStatus::READY; + } else { + $service->status = ServiceStatus::FAILED; + } + $service->save(); + })->onConnection('ssh'); + } + + public function disable(Service $service): void + { + $service->status = ServiceStatus::DISABLING; + $service->save(); + dispatch(function () use ($service) { + $status = $service->server->systemd()->disable($service->unit); + if (str($status)->contains('Active: inactive')) { + $service->status = ServiceStatus::DISABLED; + } else { + $service->status = ServiceStatus::FAILED; + } + $service->save(); + })->onConnection('ssh'); + } } diff --git a/app/Enums/ServiceStatus.php b/app/Enums/ServiceStatus.php index d925aeb..f6cc446 100644 --- a/app/Enums/ServiceStatus.php +++ b/app/Enums/ServiceStatus.php @@ -23,4 +23,10 @@ final class ServiceStatus extends Enum const RESTARTING = 'restarting'; const STOPPED = 'stopped'; + + const ENABLING = 'enabling'; + + const DISABLING = 'disabling'; + + const DISABLED = 'disabled'; } diff --git a/app/Http/Controllers/ServiceController.php b/app/Http/Controllers/ServiceController.php index 8e6b4ff..6a5e7ce 100644 --- a/app/Http/Controllers/ServiceController.php +++ b/app/Http/Controllers/ServiceController.php @@ -44,4 +44,22 @@ public function restart(Server $server, Service $service): RedirectResponse return back(); } + + public function enable(Server $server, Service $service): RedirectResponse + { + $service->enable(); + + Toast::success('Service is being enabled!'); + + return back(); + } + + public function disable(Server $server, Service $service): RedirectResponse + { + $service->disable(); + + Toast::success('Service is being disabled!'); + + return back(); + } } diff --git a/app/Models/Service.php b/app/Models/Service.php index 2ceeecd..6c30d88 100755 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -93,4 +93,14 @@ public function restart(): void { app(Manage::class)->restart($this); } + + public function enable(): void + { + app(Manage::class)->enable($this); + } + + public function disable(): void + { + app(Manage::class)->disable($this); + } } diff --git a/app/SSH/Systemd/Systemd.php b/app/SSH/Systemd/Systemd.php index 171c8b4..74e8a2a 100644 --- a/app/SSH/Systemd/Systemd.php +++ b/app/SSH/Systemd/Systemd.php @@ -13,7 +13,7 @@ public function __construct(protected Server $server) public function status(string $unit): string { $command = <<server->ssh()->exec($command, sprintf('status-%s', $unit)); @@ -22,8 +22,8 @@ public function status(string $unit): string public function start(string $unit): string { $command = <<server->ssh()->exec($command, sprintf('start-%s', $unit)); @@ -32,8 +32,8 @@ public function start(string $unit): string public function stop(string $unit): string { $command = <<server->ssh()->exec($command, sprintf('stop-%s', $unit)); @@ -42,10 +42,32 @@ public function stop(string $unit): string public function restart(string $unit): string { $command = <<server->ssh()->exec($command, sprintf('restart-%s', $unit)); } + + public function enable(string $unit): string + { + $command = <<server->ssh()->exec($command, sprintf('enable-%s', $unit)); + } + + public function disable(string $unit): string + { + $command = <<server->ssh()->exec($command, sprintf('disable-%s', $unit)); + } } diff --git a/database/migrations/2021_06_23_214143_create_services_table.php b/database/migrations/2021_06_23_214143_create_services_table.php index 360db98..1ff1cc4 100755 --- a/database/migrations/2021_06_23_214143_create_services_table.php +++ b/database/migrations/2021_06_23_214143_create_services_table.php @@ -16,7 +16,7 @@ public function up(): void $table->json('type_data')->nullable(); $table->string('name'); $table->string('version'); - $table->enum('status', ServiceStatus::getValues())->default(ServiceStatus::INSTALLING); + $table->string('status')->default(ServiceStatus::INSTALLING); $table->boolean('is_default')->default(1); $table->string('unit')->nullable(); $table->timestamps(); diff --git a/database/migrations/2021_07_02_065815_create_deployments_table.php b/database/migrations/2021_07_02_065815_create_deployments_table.php index 1e11391..e93c601 100755 --- a/database/migrations/2021_07_02_065815_create_deployments_table.php +++ b/database/migrations/2021_07_02_065815_create_deployments_table.php @@ -1,6 +1,5 @@ unsignedInteger('log_id')->nullable(); $table->json('commit_data')->nullable(); $table->string('commit_id')->nullable(); - $table->enum('status', DeploymentStatus::getValues()); + $table->string('status'); $table->timestamps(); }); } diff --git a/database/migrations/2021_07_03_133319_create_databases_table.php b/database/migrations/2021_07_03_133319_create_databases_table.php index 62f5a0d..0d9cebb 100755 --- a/database/migrations/2021_07_03_133319_create_databases_table.php +++ b/database/migrations/2021_07_03_133319_create_databases_table.php @@ -13,7 +13,7 @@ public function up(): void $table->id(); $table->unsignedBigInteger('server_id'); $table->string('name'); - $table->enum('status', DatabaseStatus::getValues())->default(DatabaseStatus::CREATING); + $table->string('status')->default(DatabaseStatus::CREATING); $table->timestamps(); }); } diff --git a/database/migrations/2021_07_03_133327_create_database_users_table.php b/database/migrations/2021_07_03_133327_create_database_users_table.php index c829f74..f67aa09 100755 --- a/database/migrations/2021_07_03_133327_create_database_users_table.php +++ b/database/migrations/2021_07_03_133327_create_database_users_table.php @@ -16,7 +16,7 @@ public function up(): void $table->longText('password')->nullable(); $table->json('databases')->nullable(); $table->string('host')->default('localhost'); - $table->enum('status', DatabaseUserStatus::getValues())->default(DatabaseUserStatus::CREATING); + $table->string('status')->default(DatabaseUserStatus::CREATING); $table->timestamps(); }); } diff --git a/database/migrations/2021_07_30_204454_create_cron_jobs_table.php b/database/migrations/2021_07_30_204454_create_cron_jobs_table.php index 106093b..c62848b 100755 --- a/database/migrations/2021_07_30_204454_create_cron_jobs_table.php +++ b/database/migrations/2021_07_30_204454_create_cron_jobs_table.php @@ -1,6 +1,5 @@ string('user'); $table->string('frequency'); $table->boolean('hidden')->default(0); - $table->enum('status', CronjobStatus::getValues()); + $table->string('status'); $table->timestamps(); }); } diff --git a/database/migrations/2021_08_14_165326_create_ssls_table.php b/database/migrations/2021_08_14_165326_create_ssls_table.php index 020e297..b85bcbf 100644 --- a/database/migrations/2021_08_14_165326_create_ssls_table.php +++ b/database/migrations/2021_08_14_165326_create_ssls_table.php @@ -1,6 +1,5 @@ longText('pk')->nullable(); $table->longText('ca')->nullable(); $table->timestamp('expires_at'); - $table->enum('status', SslStatus::getValues()); + $table->string('status'); $table->timestamps(); }); } diff --git a/database/migrations/2021_08_27_064512_create_queues_table.php b/database/migrations/2021_08_27_064512_create_queues_table.php index 9937464..a83896d 100644 --- a/database/migrations/2021_08_27_064512_create_queues_table.php +++ b/database/migrations/2021_08_27_064512_create_queues_table.php @@ -1,6 +1,5 @@ tinyInteger('numprocs')->default(8); $table->boolean('redirect_stderr')->default(1); $table->string('stdout_logfile')->nullable(); - $table->enum('status', QueueStatus::getValues()); + $table->string('status'); $table->timestamps(); }); } diff --git a/database/migrations/2021_08_30_174511_create_server_ssh_keys_table.php b/database/migrations/2021_08_30_174511_create_server_ssh_keys_table.php index 6c91a28..b093179 100644 --- a/database/migrations/2021_08_30_174511_create_server_ssh_keys_table.php +++ b/database/migrations/2021_08_30_174511_create_server_ssh_keys_table.php @@ -1,6 +1,5 @@ id(); $table->unsignedBigInteger('server_id'); $table->unsignedBigInteger('ssh_key_id'); - $table->enum('status', SshKeyStatus::getValues()); + $table->string('status'); $table->timestamps(); }); } diff --git a/resources/views/services/partials/services-list.blade.php b/resources/views/services/partials/services-list.blade.php index 12fb581..dab4f6a 100644 --- a/resources/views/services/partials/services-list.blade.php +++ b/resources/views/services/partials/services-list.blade.php @@ -54,6 +54,22 @@ class="cursor-pointer" > {{ __("Restart") }} + + @if ($service->status == \App\Enums\ServiceStatus::DISABLED) + + {{ __("Enable") }} + + @endif + + + {{ __("Disable") }} + @endif diff --git a/resources/views/services/partials/status.blade.php b/resources/views/services/partials/status.blade.php index 9ed8a11..fa2812e 100644 --- a/resources/views/services/partials/status.blade.php +++ b/resources/views/services/partials/status.blade.php @@ -33,3 +33,15 @@ @if ($status == \App\Enums\ServiceStatus::STOPPED) {{ $status }} @endif + +@if ($status == \App\Enums\ServiceStatus::ENABLING) + {{ $status }} +@endif + +@if ($status == \App\Enums\ServiceStatus::DISABLING) + {{ $status }} +@endif + +@if ($status == \App\Enums\ServiceStatus::DISABLED) + {{ $status }} +@endif diff --git a/routes/server.php b/routes/server.php index 9cab68b..c50c055 100644 --- a/routes/server.php +++ b/routes/server.php @@ -119,6 +119,8 @@ Route::get('/{server}/services/{service}/start', [ServiceController::class, 'start'])->name('servers.services.start'); Route::get('/{server}/services/{service}/stop', [ServiceController::class, 'stop'])->name('servers.services.stop'); Route::get('/{server}/services/{service}/restart', [ServiceController::class, 'restart'])->name('servers.services.restart'); + Route::get('/{server}/services/{service}/enable', [ServiceController::class, 'enable'])->name('servers.services.enable'); + Route::get('/{server}/services/{service}/disable', [ServiceController::class, 'disable'])->name('servers.services.disable'); }); // settings diff --git a/tests/Feature/ServicesTest.php b/tests/Feature/ServicesTest.php index 3a7783e..f65c93a 100644 --- a/tests/Feature/ServicesTest.php +++ b/tests/Feature/ServicesTest.php @@ -44,6 +44,27 @@ public function test_restart_service(string $name): void $this->assertEquals(ServiceStatus::READY, $service->status); } + /** + * @dataProvider data + */ + public function test_failed_to_restart_service(string $name): void + { + $this->actingAs($this->user); + + $service = $this->server->services()->where('name', $name)->firstOrFail(); + + SSH::fake('Active: inactive'); + + $this->get(route('servers.services.restart', [ + 'server' => $this->server, + 'service' => $service, + ]))->assertSessionDoesntHaveErrors(); + + $service->refresh(); + + $this->assertEquals(ServiceStatus::FAILED, $service->status); + } + /** * @dataProvider data */ @@ -65,6 +86,27 @@ public function test_stop_service(string $name): void $this->assertEquals(ServiceStatus::STOPPED, $service->status); } + /** + * @dataProvider data + */ + public function test_failed_to_stop_service(string $name): void + { + $this->actingAs($this->user); + + $service = $this->server->services()->where('name', $name)->firstOrFail(); + + SSH::fake('Active: active'); + + $this->get(route('servers.services.stop', [ + 'server' => $this->server, + 'service' => $service, + ]))->assertSessionDoesntHaveErrors(); + + $service->refresh(); + + $this->assertEquals(ServiceStatus::FAILED, $service->status); + } + /** * @dataProvider data */ @@ -110,7 +152,28 @@ public function test_failed_to_start_service(string $name): void /** * @dataProvider data */ - public function test_failed_to_restart_service(string $name): void + public function test_enable_service(string $name): void + { + $this->actingAs($this->user); + + $service = $this->server->services()->where('name', $name)->firstOrFail(); + + SSH::fake('Active: active'); + + $this->get(route('servers.services.enable', [ + 'server' => $this->server, + 'service' => $service, + ]))->assertSessionDoesntHaveErrors(); + + $service->refresh(); + + $this->assertEquals(ServiceStatus::READY, $service->status); + } + + /** + * @dataProvider data + */ + public function test_failed_to_enable_service(string $name): void { $this->actingAs($this->user); @@ -118,7 +181,7 @@ public function test_failed_to_restart_service(string $name): void SSH::fake('Active: inactive'); - $this->get(route('servers.services.restart', [ + $this->get(route('servers.services.enable', [ 'server' => $this->server, 'service' => $service, ]))->assertSessionDoesntHaveErrors(); @@ -131,7 +194,28 @@ public function test_failed_to_restart_service(string $name): void /** * @dataProvider data */ - public function test_failed_to_stop_service(string $name): void + public function test_disable_service(string $name): void + { + $this->actingAs($this->user); + + $service = $this->server->services()->where('name', $name)->firstOrFail(); + + SSH::fake('Active: inactive'); + + $this->get(route('servers.services.disable', [ + 'server' => $this->server, + 'service' => $service, + ]))->assertSessionDoesntHaveErrors(); + + $service->refresh(); + + $this->assertEquals(ServiceStatus::DISABLED, $service->status); + } + + /** + * @dataProvider data + */ + public function test_failed_to_disable_service(string $name): void { $this->actingAs($this->user); @@ -139,7 +223,7 @@ public function test_failed_to_stop_service(string $name): void SSH::fake('Active: active'); - $this->get(route('servers.services.stop', [ + $this->get(route('servers.services.disable', [ 'server' => $this->server, 'service' => $service, ]))->assertSessionDoesntHaveErrors();