route('server')); return inertia('services/Create', [ 'server' => $server, 'services' => config('keystone.services'), ]); } public function store(StoreServiceRequest $request): RedirectResponse { $server = Server::findOrFail($request->route('server')); $service = app(CreateService::class)->execute( server: $server, name: $request->name, category: $request->enum('category', ServiceCategory::class), type: $request->enum('type', ServiceType::class), version: $request->version, ); return redirect()->route('servers.show', [ 'organisation' => $server->organisation->id, 'server' => $server->id, ])->with([ 'success' => 'Service created successfully', 'service' => $service, ]); } public function show(Request $request): Response { $server = Server::findOrFail($request->route('server')); $service = $server->services() ->with(['replicas', 'slices', 'endpoints', 'operations.steps', 'operations.children.target', 'environment.application']) ->findOrFail($request->route('service')); return inertia('services/Show', [ 'server' => $server, 'service' => $service, ]); } public function showForEnvironment(Request $request): Response { $organisation = Organisation::findOrFail($request->route('organisation')); $application = $organisation->applications()->findOrFail($request->route('application')); $environment = $application->environments()->findOrFail($request->route('environment')); $service = $environment->services() ->with(['server', 'replicas', 'slices', 'endpoints', 'operations.steps', 'operations.children.target', 'environment.application']) ->findOrFail($request->route('service')); return inertia('services/Show', [ 'server' => $service->server, 'service' => $service, 'environment' => $environment, 'application' => $application, ]); } public function edit(Request $request): Response { $server = Server::findOrFail($request->route('server')); $service = $server->services()->findOrFail($request->route('service')); return inertia('services/Edit', [ 'server' => $server, 'service' => $service, 'deployPolicies' => array_values(DeployPolicy::toArray()), ]); } public function update(UpdateServiceRequest $request): RedirectResponse { $server = Server::findOrFail($request->route('server')); $service = $server->services()->findOrFail($request->route('service')); $validated = $request->validated(); $service->update([ 'name' => $validated['name'], 'desired_replicas' => $validated['desired_replicas'], 'default_cpu_limit' => $validated['default_cpu_limit'] ?? null, 'default_memory_limit_mb' => $validated['default_memory_limit_mb'] ?? null, 'deploy_policy' => $request->enum('deploy_policy', DeployPolicy::class) ?? $service->deploy_policy, 'version_track' => $validated['version_track'] ?? $service->version_track, 'available_image_digest' => $validated['available_image_digest'] ?? null, 'process_roles' => collect(explode(',', $validated['process_roles'] ?? '')) ->map(fn (string $role): string => trim($role)) ->filter() ->values() ->all(), 'config' => [ ...($service->config ?? []), 'migration_mode' => $validated['migration_mode'] ?? null, 'migration_timing' => $validated['migration_timing'] ?? null, 'migration_command' => $validated['migration_command'] ?? null, 'health_path' => $validated['health_path'] ?? null, 'backup_enabled' => $request->boolean('backup_enabled'), 'backup_command' => $validated['backup_command'] ?? null, ], ]); return redirect() ->route('services.show', [ 'organisation' => $server->organisation_id, 'server' => $server->id, 'service' => $service->id, ]) ->with('success', 'Service updated.'); } public function destroy(Request $request): RedirectResponse { $server = Server::findOrFail($request->route('server')); $service = $server->services()->findOrFail($request->route('service')); $service->delete(); return redirect() ->route('servers.show', [ 'organisation' => $server->organisation_id, 'server' => $server->id, ]) ->with('success', 'Service deleted.'); } }