Skip to content

Commit 47f221e

Browse files
authored
Add reload option to services (#920)
1 parent 280e306 commit 47f221e

File tree

12 files changed

+151
-3
lines changed

12 files changed

+151
-3
lines changed

app/Actions/Service/Manage.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,22 @@ public function restart(Service $service): void
5656
})->onQueue('ssh');
5757
}
5858

59+
public function reload(Service $service): void
60+
{
61+
$this->validate($service);
62+
$service->status = ServiceStatus::RELOADING;
63+
$service->save();
64+
dispatch(function () use ($service): void {
65+
$status = $service->server->systemd()->reload($service->handler()->unit());
66+
if (str($status)->contains('Active: active')) {
67+
$service->status = ServiceStatus::READY;
68+
} else {
69+
$service->status = ServiceStatus::FAILED;
70+
}
71+
$service->save();
72+
})->onQueue('ssh');
73+
}
74+
5975
public function enable(Service $service): void
6076
{
6177
$this->validate($service);

app/Enums/ServiceStatus.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ enum ServiceStatus: string implements VitoEnum
1414
case STARTING = 'starting';
1515
case STOPPING = 'stopping';
1616
case RESTARTING = 'restarting';
17+
case RELOADING = 'reloading';
1718
case STOPPED = 'stopped';
1819
case ENABLING = 'enabling';
1920
case DISABLING = 'disabling';
@@ -28,6 +29,7 @@ public function getColor(): string
2829
self::UNINSTALLING,
2930
self::STOPPING,
3031
self::RESTARTING,
32+
self::RELOADING,
3133
self::ENABLING,
3234
self::DISABLING => 'warning',
3335
self::INSTALLATION_FAILED,

app/Http/Controllers/API/ServiceController.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,18 @@ public function restart(Project $project, Server $server, Service $service): \Il
7676
return response()->noContent();
7777
}
7878

79+
#[Post('{service}/reload', name: 'api.projects.servers.services.reload', middleware: 'ability:write')]
80+
public function reload(Project $project, Server $server, Service $service): \Illuminate\Http\Response
81+
{
82+
$this->authorize('update', [$service, $server]);
83+
84+
$this->validateRoute($project, $server, $service);
85+
86+
app(Manage::class)->reload($service);
87+
88+
return response()->noContent();
89+
}
90+
7991
#[Post('{service}/enable', name: 'api.projects.servers.services.enable', middleware: 'ability:write')]
8092
public function enable(Project $project, Server $server, Service $service): \Illuminate\Http\Response
8193
{

app/Http/Controllers/ServiceController.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,18 @@ public function restart(Server $server, Service $service): RedirectResponse
8989
]));
9090
}
9191

92+
#[Post('/{service}/reload', name: 'services.reload')]
93+
public function reload(Server $server, Service $service): RedirectResponse
94+
{
95+
$this->authorize('reload', $service);
96+
97+
app(Manage::class)->reload($service);
98+
99+
return back()->with('success', __(':service is being reloaded.', [
100+
'service' => $service->name,
101+
]));
102+
}
103+
92104
#[Post('/{service}/stop', name: 'services.stop')]
93105
public function stop(Server $server, Service $service): RedirectResponse
94106
{

app/Models/Service.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,11 @@ public function restart(): void
102102
$this->handler()->unit() && app(Manage::class)->restart($this);
103103
}
104104

105+
public function reload(): void
106+
{
107+
$this->handler()->unit() && app(Manage::class)->reload($this);
108+
}
109+
105110
public function enable(): void
106111
{
107112
$this->handler()->unit() && app(Manage::class)->enable($this);

app/Policies/ServicePolicy.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,11 @@ public function restart(User $user, Service $service): bool
5959
return $this->update($user, $service);
6060
}
6161

62+
public function reload(User $user, Service $service): bool
63+
{
64+
return $this->update($user, $service);
65+
}
66+
6267
public function disable(User $user, Service $service): bool
6368
{
6469
return $this->update($user, $service);

app/SSH/OS/Systemd.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,11 +93,11 @@ public function disable(string $unit): string
9393
*/
9494
public function reload(string $unit): string
9595
{
96-
$command = <<<'EOD'
96+
$command = <<<EOD
9797
sudo systemctl reload $unit
9898
sudo systemctl status $unit | cat
9999
EOD;
100100

101-
return $this->server->ssh()->exec($command, 'reload-'.$unit);
101+
return $this->server->ssh()->exec($command, sprintf('reload-%s', $unit));
102102
}
103103
}

public/api-docs/openapi/services.yaml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,58 @@ paths:
363363
schema:
364364
$ref: './openapi/schemas/ErrorResponse.yaml'
365365

366+
/api/projects/{project}/servers/{server}/services/{service}/reload:
367+
post:
368+
summary: Reload service
369+
description: Reload a service to apply configuration changes without fully restarting
370+
tags:
371+
- Services
372+
security:
373+
- bearerAuth: []
374+
parameters:
375+
- name: project
376+
in: path
377+
required: true
378+
description: Project ID
379+
schema:
380+
type: integer
381+
example: 1
382+
- name: server
383+
in: path
384+
required: true
385+
description: Server ID
386+
schema:
387+
type: integer
388+
example: 1
389+
- name: service
390+
in: path
391+
required: true
392+
description: Service ID
393+
schema:
394+
type: integer
395+
example: 1
396+
responses:
397+
'204':
398+
description: Service reloaded successfully
399+
'401':
400+
description: Unauthorized
401+
content:
402+
application/json:
403+
schema:
404+
$ref: './openapi/schemas/ErrorResponse.yaml'
405+
'403':
406+
description: Forbidden
407+
content:
408+
application/json:
409+
schema:
410+
$ref: './openapi/schemas/ErrorResponse.yaml'
411+
'404':
412+
description: Service not found
413+
content:
414+
application/json:
415+
schema:
416+
$ref: './openapi/schemas/ErrorResponse.yaml'
417+
366418
/api/projects/{project}/servers/{server}/services/{service}/enable:
367419
post:
368420
summary: Enable service

resources/js/pages/php/components/columns.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ export const columns: ColumnDef<Service>[] = [
7272
<Action type="start" service={row.original} />
7373
<Action type="stop" service={row.original} />
7474
<Action type="restart" service={row.original} />
75+
<Action type="reload" service={row.original} />
7576
<Action type="enable" service={row.original} />
7677
<Action type="disable" service={row.original} />
7778
<DropdownMenuSeparator />

resources/js/pages/services/components/action.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ import { LoaderCircleIcon } from 'lucide-react';
1717
import FormSuccessful from '@/components/form-successful';
1818
import InputError from '@/components/ui/input-error';
1919

20-
export function Action({ type, service }: { type: 'start' | 'stop' | 'restart' | 'enable' | 'disable'; service: Service }) {
20+
export function Action({ type, service }: { type: 'start' | 'stop' | 'restart' | 'reload' | 'enable' | 'disable'; service: Service }) {
2121
const [open, setOpen] = useState(false);
2222
const form = useForm();
2323

0 commit comments

Comments
 (0)