From fae97e4dee198d2bfd86c82290f397e51b198027 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 27 Nov 2023 09:58:31 +0100 Subject: [PATCH] Fix network connection issues in Server and Service models --- app/Http/Livewire/Server/Show.php | 1 + app/Models/Service.php | 6 +++ bootstrap/helpers/proxy.php | 10 +++- bootstrap/helpers/shared.php | 85 ++++++++++++++++++++++++++++++- 4 files changed, 99 insertions(+), 3 deletions(-) diff --git a/app/Http/Livewire/Server/Show.php b/app/Http/Livewire/Server/Show.php index 3863381b2..a72abdf94 100644 --- a/app/Http/Livewire/Server/Show.php +++ b/app/Http/Livewire/Server/Show.php @@ -19,6 +19,7 @@ public function mount() if (is_null($this->server)) { return redirect()->route('server.all'); } + } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Models/Service.php b/app/Models/Service.php index 345e4db92..3a02ed560 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -442,4 +442,10 @@ public function parse(bool $isNew = false): Collection { return parseDockerComposeFile($this, $isNew); } + public function networks() + { + $networks = getTopLevelNetworks($this); + // ray($networks); + return $networks; + } } diff --git a/bootstrap/helpers/proxy.php b/bootstrap/helpers/proxy.php index 595d6c5ad..86946231b 100644 --- a/bootstrap/helpers/proxy.php +++ b/bootstrap/helpers/proxy.php @@ -12,10 +12,16 @@ function get_proxy_path() } function connectProxyToNetworks(Server $server) { - // TODO: Connect to service + compose based application networks as well. + // TODO: Connect to compose based application networks as well. + // Standalone networks $networks = collect($server->standaloneDockers)->map(function ($docker) { return $docker['network']; - })->unique(); + }); + // Service networks + foreach($server->services()->get() as $service) { + $networks->push($service->networks()); + } + $networks = collect($networks)->flatten()->unique(); if ($networks->count() === 0) { $networks = collect(['coolify']); } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index cff60233a..4f47d2332 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -495,6 +495,89 @@ function removeAnsiColors($text) return preg_replace('/\e[[][A-Za-z0-9];?[0-9]*m?/', '', $text); } +function getTopLevelNetworks(Service|Application $resource) +{ + if ($resource->getMorphClass() === 'App\Models\Service') { + if ($resource->docker_compose_raw) { + try { + $yaml = Yaml::parse($resource->docker_compose_raw); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + $services = data_get($yaml, 'services'); + $topLevelNetworks = collect(data_get($yaml, 'networks', [])); + $definedNetwork = collect([$resource->uuid]); + $services = collect($services)->map(function ($service, $_) use ($topLevelNetworks, $definedNetwork) { + $serviceNetworks = collect(data_get($service, 'networks', [])); + + // Collect/create/update networks + if ($serviceNetworks->count() > 0) { + foreach ($serviceNetworks as $networkName => $networkDetails) { + $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { + return $value == $networkName || $key == $networkName; + }); + if (!$networkExists) { + $topLevelNetworks->put($networkDetails, null); + } + } + } + + $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { + return $value == $definedNetwork; + }); + if (!$definedNetworkExists) { + foreach ($definedNetwork as $network) { + $topLevelNetworks->put($network, [ + 'name' => $network, + 'external' => true + ]); + } + } + + return $service; + }); + return $topLevelNetworks->keys(); + } + } else if ($resource->getMorphClass() === 'App\Models\Application') { + try { + $yaml = Yaml::parse($resource->docker_compose_raw); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + $server = $resource->destination->server; + $topLevelNetworks = collect(data_get($yaml, 'networks', [])); + $services = data_get($yaml, 'services'); + $definedNetwork = collect([$resource->uuid]); + $services = collect($services)->map(function ($service, $_) use ($topLevelNetworks, $definedNetwork) { + $serviceNetworks = collect(data_get($service, 'networks', [])); + + // Collect/create/update networks + if ($serviceNetworks->count() > 0) { + foreach ($serviceNetworks as $networkName => $networkDetails) { + $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { + return $value == $networkName || $key == $networkName; + }); + if (!$networkExists) { + $topLevelNetworks->put($networkDetails, null); + } + } + } + $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) { + return $value == $definedNetwork; + }); + if (!$definedNetworkExists) { + foreach ($definedNetwork as $network) { + $topLevelNetworks->put($network, [ + 'name' => $network, + 'external' => true + ]); + } + } + return $service; + }); + return $topLevelNetworks->keys(); + } +} function parseDockerComposeFile(Service|Application $resource, bool $isNew = false) { ray()->clearAll(); @@ -1010,7 +1093,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $resource->docker_compose = Yaml::dump($finalServices, 10, 2); $resource->save(); $resource->saveComposeConfigs(); - return collect([]); + return $finalServices; } else { return collect([]); }