From c8d48ccbff3a5abeb3dffc2fa65116c67152e63b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 14 Mar 2024 09:21:48 +0100 Subject: [PATCH] fix: docker compose validation --- app/Livewire/Project/New/DockerCompose.php | 9 +++++--- .../Project/Service/Configuration.php | 10 ++++++--- app/Livewire/Project/Service/StackForm.php | 5 ++++- bootstrap/helpers/docker.php | 21 +++++++++++++++++++ 4 files changed, 38 insertions(+), 7 deletions(-) diff --git a/app/Livewire/Project/New/DockerCompose.php b/app/Livewire/Project/New/DockerCompose.php index dea5eca3e..79394d310 100644 --- a/app/Livewire/Project/New/DockerCompose.php +++ b/app/Livewire/Project/New/DockerCompose.php @@ -17,7 +17,6 @@ class DockerCompose extends Component public array $query; public function mount() { - $this->parameters = get_route_parameters(); $this->query = request()->query(); if (isDev()) { @@ -40,12 +39,17 @@ class DockerCompose extends Component } public function submit() { + $server_id = $this->query['server_id']; try { $this->validate([ 'dockerComposeRaw' => 'required' ]); $this->dockerComposeRaw = Yaml::dump(Yaml::parse($this->dockerComposeRaw), 10, 2, Yaml::DUMP_MULTI_LINE_LITERAL_BLOCK); - $server_id = $this->query['server_id']; + + $isValid = validateComposeFile($this->dockerComposeRaw, $server_id); + if ($isValid !== 'OK') { + return $this->dispatch('error', "Invalid docker-compose file.\n$isValid"); + } $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('name', $this->parameters['environment_name'])->first(); @@ -74,7 +78,6 @@ class DockerCompose extends Component 'environment_name' => $environment->name, 'project_uuid' => $project->uuid, ]); - } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php index 69d158c04..eb72c803c 100644 --- a/app/Livewire/Project/Service/Configuration.php +++ b/app/Livewire/Project/Service/Configuration.php @@ -38,8 +38,12 @@ class Configuration extends Component } public function check_status() { - dispatch_sync(new ContainerStatusJob($this->service->server)); - $this->dispatch('refresh')->self(); - $this->dispatch('serviceStatusChanged'); + try { + dispatch_sync(new ContainerStatusJob($this->service->server)); + $this->dispatch('refresh')->self(); + $this->dispatch('serviceStatusChanged'); + } catch (\Exception $e) { + return handleError($e, $this); + } } } diff --git a/app/Livewire/Project/Service/StackForm.php b/app/Livewire/Project/Service/StackForm.php index 1ec63a761..650dde792 100644 --- a/app/Livewire/Project/Service/StackForm.php +++ b/app/Livewire/Project/Service/StackForm.php @@ -41,7 +41,6 @@ class StackForm extends Component } public function saveCompose($raw) { - $this->service->docker_compose_raw = $raw; $this->submit(); } @@ -55,6 +54,10 @@ class StackForm extends Component { try { $this->validate(); + $isValid = validateComposeFile($this->service->docker_compose_raw, $this->service->server->id); + if ($isValid !== 'OK') { + throw new \Exception("Invalid docker-compose file.\n$isValid"); + } $this->service->save(); $this->service->saveExtraFields($this->fields); $this->service->parse(); diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 754e65a97..9c56b627d 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -556,3 +556,24 @@ function convert_docker_run_to_compose(?string $custom_docker_run_options = null } return $compose_options->toArray(); } + +function validateComposeFile(string $compose, int $server_id): string|Throwable { + try { + $uuid = Str::random(10); + $server = Server::findOrFail($server_id); + $base64_compose = base64_encode($compose); + $output = instant_remote_process([ + "echo {$base64_compose} | base64 -d > /tmp/{$uuid}.yml", + "docker compose -f /tmp/{$uuid}.yml config", + ], $server); + ray($output); + return 'OK'; + } catch (\Throwable $e) { + ray($e); + return $e->getMessage(); + } finally { + instant_remote_process([ + "rm /tmp/{$uuid}.yml", + ], $server); + } +}