From 154b1b05e4e055e16d061f826a77c8ff036a20ce Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 22 Feb 2024 13:29:28 +0100 Subject: [PATCH] feat: able to add dynamic configurations from proxy dashboard --- .../Proxy/DynamicConfigurationNavbar.php | 28 ++++ .../Server/Proxy/DynamicConfigurations.php | 49 ++++++ .../Server/Proxy/NewDynamicConfiguration.php | 73 ++++++++ bootstrap/helpers/shared.php | 6 +- .../views/components/proxy/options.blade.php | 47 ------ .../views/components/server/sidebar.blade.php | 6 +- .../views/components/slide-over.blade.php | 4 +- .../views/components/team/navbar.blade.php | 2 +- resources/views/livewire/dashboard.blade.php | 2 +- .../project/shared/get-logs.blade.php | 157 +++++++++--------- .../dynamic-configuration-navbar.blade.php | 15 ++ .../proxy/dynamic-configurations.blade.php | 53 ++++++ .../livewire/server/proxy/logs.blade.php | 1 + .../proxy/new-dynamic-configuration.blade.php | 5 + routes/web.php | 2 + 15 files changed, 319 insertions(+), 131 deletions(-) create mode 100644 app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php create mode 100644 app/Livewire/Server/Proxy/DynamicConfigurations.php create mode 100644 app/Livewire/Server/Proxy/NewDynamicConfiguration.php delete mode 100644 resources/views/components/proxy/options.blade.php create mode 100644 resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php create mode 100644 resources/views/livewire/server/proxy/dynamic-configurations.blade.php create mode 100644 resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php diff --git a/app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php b/app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php new file mode 100644 index 000000000..acff38ccb --- /dev/null +++ b/app/Livewire/Server/Proxy/DynamicConfigurationNavbar.php @@ -0,0 +1,28 @@ +whereId($this->server_id)->first(); + $proxy_path = get_proxy_path(); + $file = str_replace('|', '.', $fileName); + instant_remote_process(["rm -f {$proxy_path}/dynamic/{$file}"], $server); + $this->dispatch('success', 'Success', 'File deleted.'); + $this->dispatch('loadDynamicConfigurations'); + $this->dispatch('refresh'); + } + public function render() + { + return view('livewire.server.proxy.dynamic-configuration-navbar'); + } +} diff --git a/app/Livewire/Server/Proxy/DynamicConfigurations.php b/app/Livewire/Server/Proxy/DynamicConfigurations.php new file mode 100644 index 000000000..9e7a89780 --- /dev/null +++ b/app/Livewire/Server/Proxy/DynamicConfigurations.php @@ -0,0 +1,49 @@ + '$refresh']; + protected $rules = [ + 'contents.*' => 'nullable|string', + ]; + public function loadDynamicConfigurations() + { + $proxy_path = get_proxy_path(); + $files = instant_remote_process(["mkdir -p $proxy_path/dynamic && ls -1 {$proxy_path}/dynamic"], $this->server); + $files = collect(explode("\n", $files))->filter(fn ($file) => !empty($file)); + $files = $files->map(fn ($file) => trim($file)); + $files = $files->sort(); + $files = $files->filter(fn ($file) => $file !== 'coolify.yaml')->prepend('coolify.yaml'); + $contents = collect([]); + foreach ($files as $file) { + $without_extension = str_replace('.', '|', $file); + $contents[$without_extension] = instant_remote_process(["cat {$proxy_path}/dynamic/{$file}"], $this->server); + } + $this->contents = $contents; + } + public function mount() + { + $this->parameters = get_route_parameters(); + try { + $this->server = Server::ownedByCurrentTeam()->whereUuid(request()->server_uuid)->first(); + if (is_null($this->server)) { + return redirect()->route('server.index'); + } + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() + { + return view('livewire.server.proxy.dynamic-configurations'); + } +} diff --git a/app/Livewire/Server/Proxy/NewDynamicConfiguration.php b/app/Livewire/Server/Proxy/NewDynamicConfiguration.php new file mode 100644 index 000000000..cf9c88160 --- /dev/null +++ b/app/Livewire/Server/Proxy/NewDynamicConfiguration.php @@ -0,0 +1,73 @@ +parameters = get_route_parameters(); + if ($this->fileName !== '') { + $this->fileName = str_replace('|', '.', $this->fileName); + } + } + public function addDynamicConfiguration() + { + try { + $this->validate([ + 'fileName' => 'required', + 'value' => 'required', + ]); + + if (data_get($this->parameters, 'server_uuid')) { + $this->server = Server::ownedByCurrentTeam()->whereUuid(data_get($this->parameters, 'server_uuid'))->first(); + } + if (!is_null($this->server_id)) { + $this->server = Server::ownedByCurrentTeam()->whereId($this->server_id)->first(); + } + if (is_null($this->server)) { + return redirect()->route('server.index'); + } + if (!str($this->fileName)->endsWith('.yaml') && !str($this->fileName)->endsWith('.yml')) { + $this->fileName = "{$this->fileName}.yaml"; + } + if ($this->fileName === 'coolify.yaml') { + $this->dispatch('error', 'Error', 'File name is reserved.'); + return; + } + $proxy_path = get_proxy_path(); + $file = "{$proxy_path}/dynamic/{$this->fileName}"; + if ($this->newFile) { + $exists = instant_remote_process(["test -f $file && echo 1 || echo 0"], $this->server); + if ($exists == 1) { + $this->dispatch('error', 'Error', 'File already exists'); + return; + } + } + $yaml = Yaml::parse($this->value); + $yaml = Yaml::dump($yaml, 10, 2); + $this->value = $yaml; + $base64_value = base64_encode($this->value); + instant_remote_process(["echo '{$base64_value}' | base64 -d > {$file}"], $this->server); + $this->dispatch('loadDynamicConfigurations'); + $this->dispatch('dynamic-configuration-added'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + public function render() + { + return view('livewire.server.proxy.new-dynamic-configuration'); + } +} diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 094973a6a..ed5819494 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -104,13 +104,13 @@ function handleError(?Throwable $error = null, ?Livewire\Component $livewire = n ray($error); if ($error instanceof TooManyRequestsException) { if (isset($livewire)) { - return $livewire->dispatch('error', "Too many requests.", "Please try again in {$error->secondsUntilAvailable} seconds."); + return $livewire->dispatch('error', "Error", "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."); } return "Too many requests. Please try again in {$error->secondsUntilAvailable} seconds."; } if ($error instanceof UniqueConstraintViolationException) { if (isset($livewire)) { - return $livewire->dispatch('error', "Duplicate entry found.", "Please use a different name."); + return $livewire->dispatch('error', "Error", "Duplicate entry found. Please use a different name."); } return "Duplicate entry found. Please use a different name."; } @@ -126,7 +126,7 @@ function handleError(?Throwable $error = null, ?Livewire\Component $livewire = n if (isset($livewire)) { if (str($message)->length() > 20) { - return $livewire->dispatch('error', 'Error occured', $message); + return $livewire->dispatch('error', 'Error', $message); } return $livewire->dispatch('error', $message); } diff --git a/resources/views/components/proxy/options.blade.php b/resources/views/components/proxy/options.blade.php deleted file mode 100644 index 04a6f04ba..000000000 --- a/resources/views/components/proxy/options.blade.php +++ /dev/null @@ -1,47 +0,0 @@ -@props(['proxy_settings']) -
- -
- -
- -
- -
- Visit Dashboard -
- -
- -
- -
- -
diff --git a/resources/views/components/server/sidebar.blade.php b/resources/views/components/server/sidebar.blade.php index 9aa50bb21..86bb92a87 100644 --- a/resources/views/components/server/sidebar.blade.php +++ b/resources/views/components/server/sidebar.blade.php @@ -1,12 +1,16 @@
@if ($server->isFunctional())
-
+
@if (data_get($server, 'proxy.type') !== 'NONE') + + + diff --git a/resources/views/components/slide-over.blade.php b/resources/views/components/slide-over.blade.php index 5ea4dfe65..02dfa63c0 100644 --- a/resources/views/components/slide-over.blade.php +++ b/resources/views/components/slide-over.blade.php @@ -18,14 +18,14 @@ x-transition:leave="transform transition ease-in-out duration-100 sm:duration-300" x-transition:leave-start="translate-x-0" x-transition:leave-end="translate-x-full" @class([ - 'max-w-md w-screen' => !$fullScreen, + 'max-w-xl w-screen' => !$fullScreen, 'max-w-4xl w-screen' => $fullScreen, ])>
-

+

{{ $title }}

- - - - -
{{ $outputs }}
+
+
+
+

Container: {{ $container }}

+ @if ($streamLogs) + + @endif
-
- +
- function toggleScroll() { - this.alwaysScroll = !this.alwaysScroll; - - if (this.alwaysScroll) { - this.intervalId = setInterval(() => { - const screen = document.getElementById('screen'); - const logs = document.getElementById('logs'); - if (screen.scrollTop !== logs.scrollHeight) { - screen.scrollTop = logs.scrollHeight; - } - }, 100); - } else { - clearInterval(this.intervalId); - this.intervalId = null; - } - } - - function goTop() { - this.alwaysScroll = false; - clearInterval(this.intervalId); - const screen = document.getElementById('screen'); - screen.scrollTop = 0; - } -
diff --git a/resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php b/resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php new file mode 100644 index 000000000..c2a5dade9 --- /dev/null +++ b/resources/views/livewire/server/proxy/dynamic-configuration-navbar.blade.php @@ -0,0 +1,15 @@ +
+

File: {{ str_replace('|', '.', $fileName) }}

+
+ + Edit Configuration + + + + + +
+ Delete +
diff --git a/resources/views/livewire/server/proxy/dynamic-configurations.blade.php b/resources/views/livewire/server/proxy/dynamic-configurations.blade.php new file mode 100644 index 000000000..9cc1c505b --- /dev/null +++ b/resources/views/livewire/server/proxy/dynamic-configurations.blade.php @@ -0,0 +1,53 @@ +
+ +
+ +
+ @if ($server->isFunctional()) +
+
+
+

Dynamic Configurations

+ Reload + + New Dynamic Configuration + + + + + +
+
You can add dynamic Traefik configurations here.
+
+
+
+ +
+
+ @if ($contents?->isNotEmpty()) + @foreach ($contents as $fileName => $value) +
+ @if (str_replace('|', '.', $fileName) === 'coolify.yaml') +
+

File: {{ str_replace('|', '.', $fileName) }}

+
+ + @else + + + @endif +
+ @endforeach + @endif +
+ + @endif +
+
+
diff --git a/resources/views/livewire/server/proxy/logs.blade.php b/resources/views/livewire/server/proxy/logs.blade.php index 58e718424..496464541 100644 --- a/resources/views/livewire/server/proxy/logs.blade.php +++ b/resources/views/livewire/server/proxy/logs.blade.php @@ -3,6 +3,7 @@
+

Logs

diff --git a/resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php b/resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php new file mode 100644 index 000000000..9e98b0ed4 --- /dev/null +++ b/resources/views/livewire/server/proxy/new-dynamic-configuration.blade.php @@ -0,0 +1,5 @@ +
+ + + Save + diff --git a/routes/web.php b/routes/web.php index 9a6a6bbef..a4998aaff 100644 --- a/routes/web.php +++ b/routes/web.php @@ -67,6 +67,7 @@ use App\Livewire\Server\Resources as ResourcesShow; use App\Livewire\Server\Destination\Show as DestinationShow; use App\Livewire\Server\LogDrains; use App\Livewire\Server\PrivateKey\Show as PrivateKeyShow; +use App\Livewire\Server\Proxy\DynamicConfigurations as ProxyDynamicConfigurations; use App\Livewire\Server\Proxy\Show as ProxyShow; use App\Livewire\Server\Proxy\Logs as ProxyLogs; use App\Livewire\Source\Github\Change as GitHubChange; @@ -177,6 +178,7 @@ Route::middleware(['auth', 'verified'])->group(function () { Route::get('/', ServerShow::class)->name('server.show'); Route::get('/resources', ResourcesShow::class)->name('server.resources'); Route::get('/proxy', ProxyShow::class)->name('server.proxy'); + Route::get('/proxy/dynamic', ProxyDynamicConfigurations::class)->name('server.proxy.dynamic-confs'); Route::get('/proxy/logs', ProxyLogs::class)->name('server.proxy.logs'); Route::get('/private-key', PrivateKeyShow::class)->name('server.private-key'); Route::get('/destinations', DestinationShow::class)->name('server.destinations');