From 555dc1a9b5a08721f36525397d2b247eb819b0bc Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Mon, 12 Aug 2024 17:36:46 +0200 Subject: [PATCH 01/42] add dropdown without content --- resources/views/livewire/server/form.blade.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index 3c137df91..4b310a188 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -65,7 +65,7 @@ @endif - +
--}} @endif -
+ \ No newline at end of file From ba136d43fa7a91ca3e502dadb92f7fad131c3c72 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:13:47 +0200 Subject: [PATCH 02/42] DB migration --- ..._add_timezone_to_server_settings_table.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php diff --git a/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php b/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php new file mode 100644 index 000000000..971195d6d --- /dev/null +++ b/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php @@ -0,0 +1,22 @@ +string('server_timezone')->default('UTC'); + }); + } + + public function down() + { + Schema::table('server_settings', function (Blueprint $table) { + $table->dropColumn('server_timezone'); + }); + } +} \ No newline at end of file From 228b885946ba63586dede2228f9595539b7b7ef3 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Mon, 12 Aug 2024 18:14:15 +0200 Subject: [PATCH 03/42] UI timezone settings with search --- .../views/livewire/server/form.blade.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index 4b310a188..b6f613548 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -65,7 +65,28 @@ @endif - +
+ +
+ +
+ +
+
+
Date: Mon, 12 Aug 2024 18:40:32 +0200 Subject: [PATCH 04/42] added timezone update logic --- app/Livewire/Server/Form.php | 83 +++++++++++++++++++++++++++++++++++- 1 file changed, 81 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 9934ea345..1da9237f0 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -6,6 +6,7 @@ use App\Actions\Server\StartSentinel; use App\Actions\Server\StopSentinel; use App\Jobs\PullSentinelImageJob; use App\Models\Server; +use DateTimeZone; use Livewire\Component; class Form extends Component @@ -46,6 +47,7 @@ class Form extends Component 'server.settings.metrics_history_days' => 'required|integer|min:1', 'wildcard_domain' => 'nullable|url', 'server.settings.is_server_api_enabled' => 'required|boolean', + 'server.settings.server_timezone' => 'required|string|timezone', ]; protected $validationAttributes = [ @@ -66,10 +68,15 @@ class Form extends Component 'server.settings.metrics_refresh_rate_seconds' => 'Metrics Interval', 'server.settings.metrics_history_days' => 'Metrics History', 'server.settings.is_server_api_enabled' => 'Server API', + 'server.settings.server_timezone' => 'Server Timezone', ]; - public function mount() + public $timezones; + + public function mount(Server $server) { + $this->server = $server; + $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); $this->wildcard_domain = $this->server->settings->wildcard_domain; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; } @@ -191,8 +198,80 @@ class Form extends Component refresh_server_connection($this->server->privateKey); $this->server->settings->wildcard_domain = $this->wildcard_domain; $this->server->settings->cleanup_after_percentage = $this->cleanup_after_percentage; + + // Update the timezone if it has changed + if ($this->server->settings->isDirty('server_timezone')) { + try { + $message = $this->updateServerTimezone($this->server->settings->server_timezone); + $this->dispatch('success', $message); + } catch (\Exception $e) { + $this->dispatch('error', 'Failed to update server timezone: ' . $e->getMessage()); + return; + } + } + $this->server->settings->save(); $this->server->save(); $this->dispatch('success', 'Server updated.'); } -} + + public function updatedServerTimezone($value) + { + if (!is_string($value) || !in_array($value, timezone_identifiers_list())) { + $this->addError('server.settings.server_timezone', 'Invalid timezone.'); + return; + } + $this->server->settings->server_timezone = $value; + } + + private function updateServerTimezone($value) + { + $commands = [ + "date +%Z", + "if command -v timedatectl >/dev/null 2>&1; then timedatectl set-timezone " . escapeshellarg($value) . " 2>&1 || echo 'timedatectl failed'; fi", + "if [ -f /etc/timezone ]; then echo " . escapeshellarg($value) . " > /etc/timezone && dpkg-reconfigure -f noninteractive tzdata 2>&1 || echo '/etc/timezone update failed'; fi", + "if [ -L /etc/localtime ]; then ln -sf /usr/share/zoneinfo/" . escapeshellarg($value) . " /etc/localtime 2>&1 || echo '/etc/localtime update failed'; fi", + "date +%Z", + ]; + + $result = instant_remote_process($commands, $this->server); + + if (!isset($result['output']) || empty($result['output'])) { + throw new \Exception("No output received from server. The timezone may not have been updated."); + } + + $output = is_array($result['output']) ? $result['output'] : explode("\n", trim($result['output'])); + $output = array_filter($output); // Remove empty lines + + if (count($output) < 2) { + throw new \Exception("Unexpected output format: " . implode("\n", $output)); + } + + $oldTimezone = $output[0]; + $newTimezone = end($output); + + $errors = array_filter($output, function($line) { + return strpos($line, 'failed') !== false; + }); + + if (!empty($errors)) { + throw new \Exception("Timezone change failed. Errors: " . implode(", ", $errors)); + } + + if ($oldTimezone === $newTimezone) { + throw new \Exception("Timezone change failed. The timezone is still set to {$oldTimezone}."); + } + + try { + $dateTime = new \DateTime('now', new \DateTimeZone($value)); + $phpTimezone = $dateTime->getTimezone()->getName(); + } catch (\Exception $e) { + throw new \Exception("Invalid PHP timezone: {$value}. Error: " . $e->getMessage()); + } + + $this->server->settings->server_timezone = $phpTimezone; + $this->server->settings->save(); + + return "Timezone successfully changed from {$oldTimezone} to {$newTimezone} (PHP: {$phpTimezone})."; + } +} \ No newline at end of file From dab0cc8cbd5f355bbcae803db2b823572703b940 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:00:13 +0200 Subject: [PATCH 05/42] fix form input --- resources/views/livewire/server/form.blade.php | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index b6f613548..635e5e316 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -65,15 +65,28 @@ @endif -
+
From 777913923f879b7947b44abd177ecbaef06e985a Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:00:39 +0200 Subject: [PATCH 06/42] fix faulty DB migration and remove default, server is the default --- .../2024_08_12_155023_add_timezone_to_server_settings_table.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php b/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php index 971195d6d..62511ffb3 100644 --- a/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php +++ b/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php @@ -9,7 +9,7 @@ class AddTimezoneToServerSettingsTable extends Migration public function up() { Schema::table('server_settings', function (Blueprint $table) { - $table->string('server_timezone')->default('UTC'); + $table->string('server_timezone')->default(''); }); } From 99f2d4d71113c7f693fbfd90bedecfdb17110ec2 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:18:55 +0200 Subject: [PATCH 07/42] Feat: actually update timezone on the server --- app/Livewire/Server/Form.php | 130 +++++++++++++++++++++-------------- 1 file changed, 79 insertions(+), 51 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 1da9237f0..318b0a8b4 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -5,8 +5,7 @@ namespace App\Livewire\Server; use App\Actions\Server\StartSentinel; use App\Actions\Server\StopSentinel; use App\Jobs\PullSentinelImageJob; -use App\Models\Server; -use DateTimeZone; +use App\Models\Server;; use Livewire\Component; class Form extends Component @@ -179,7 +178,8 @@ class Form extends Component public function submit() { - if (isCloud() && ! isDev()) { + ray('Submit method called'); + if (isCloud() && !isDev()) { $this->validate(); $this->validate([ 'server.ip' => 'required', @@ -192,29 +192,50 @@ class Form extends Component })->pluck('ip')->toArray(); if (in_array($this->server->ip, $uniqueIPs)) { $this->dispatch('error', 'IP address is already in use by another team.'); - return; } refresh_server_connection($this->server->privateKey); $this->server->settings->wildcard_domain = $this->wildcard_domain; $this->server->settings->cleanup_after_percentage = $this->cleanup_after_percentage; - // Update the timezone if it has changed - if ($this->server->settings->isDirty('server_timezone')) { + ray('Current timezone:', $this->server->settings->getOriginal('server_timezone')); + ray('New timezone:', $this->server->settings->server_timezone); + + $currentTimezone = $this->server->settings->getOriginal('server_timezone'); + $newTimezone = $this->server->settings->server_timezone; + + ray('Comparing timezones:', $currentTimezone, $newTimezone); + + if ($currentTimezone !== $newTimezone || $currentTimezone === '') { + ray('Timezone change detected'); try { - $message = $this->updateServerTimezone($this->server->settings->server_timezone); - $this->dispatch('success', $message); + ray('Calling updateServerTimezone'); + $timezoneUpdated = $this->updateServerTimezone($newTimezone); + ray('updateServerTimezone result:', $timezoneUpdated); + if ($timezoneUpdated) { + $this->server->settings->server_timezone = $newTimezone; + $this->server->settings->save(); + ray('New timezone saved to database:', $newTimezone); + } else { + ray('Timezone update failed'); + return; + } } catch (\Exception $e) { + ray('Exception in updateServerTimezone:', $e->getMessage()); $this->dispatch('error', 'Failed to update server timezone: ' . $e->getMessage()); return; } + } else { + ray('No timezone change detected'); } + ray('Saving server settings'); $this->server->settings->save(); $this->server->save(); $this->dispatch('success', 'Server updated.'); + ray('Submit method completed'); } - + public function updatedServerTimezone($value) { if (!is_string($value) || !in_array($value, timezone_identifiers_list())) { @@ -226,52 +247,59 @@ class Form extends Component private function updateServerTimezone($value) { - $commands = [ - "date +%Z", - "if command -v timedatectl >/dev/null 2>&1; then timedatectl set-timezone " . escapeshellarg($value) . " 2>&1 || echo 'timedatectl failed'; fi", - "if [ -f /etc/timezone ]; then echo " . escapeshellarg($value) . " > /etc/timezone && dpkg-reconfigure -f noninteractive tzdata 2>&1 || echo '/etc/timezone update failed'; fi", - "if [ -L /etc/localtime ]; then ln -sf /usr/share/zoneinfo/" . escapeshellarg($value) . " /etc/localtime 2>&1 || echo '/etc/localtime update failed'; fi", - "date +%Z", - ]; - - $result = instant_remote_process($commands, $this->server); - - if (!isset($result['output']) || empty($result['output'])) { - throw new \Exception("No output received from server. The timezone may not have been updated."); - } - - $output = is_array($result['output']) ? $result['output'] : explode("\n", trim($result['output'])); - $output = array_filter($output); // Remove empty lines - - if (count($output) < 2) { - throw new \Exception("Unexpected output format: " . implode("\n", $output)); - } - - $oldTimezone = $output[0]; - $newTimezone = end($output); - - $errors = array_filter($output, function($line) { - return strpos($line, 'failed') !== false; - }); - - if (!empty($errors)) { - throw new \Exception("Timezone change failed. Errors: " . implode(", ", $errors)); - } - - if ($oldTimezone === $newTimezone) { - throw new \Exception("Timezone change failed. The timezone is still set to {$oldTimezone}."); - } - + ray('updateServerTimezone called with value:', $value); try { + $commands = [ + "date +%Z", + "if command -v timedatectl >/dev/null 2>&1; then timedatectl set-timezone " . escapeshellarg($value) . " 2>&1 || echo 'timedatectl failed'; fi", + "if [ -f /etc/timezone ]; then echo " . escapeshellarg($value) . " > /etc/timezone 2>&1 || echo '/etc/timezone update failed'; fi", + "if [ -L /etc/localtime ] || [ -f /etc/localtime ]; then ln -sf /usr/share/zoneinfo/" . escapeshellarg($value) . " /etc/localtime 2>&1 || echo '/etc/localtime update failed'; fi", + "if command -v dpkg-reconfigure >/dev/null 2>&1; then dpkg-reconfigure -f noninteractive tzdata 2>&1 || echo 'dpkg-reconfigure failed'; fi", + "if command -v apk >/dev/null 2>&1; then apk add --no-cache tzdata 2>&1 && cp /usr/share/zoneinfo/" . escapeshellarg($value) . " /etc/localtime 2>&1 && echo " . escapeshellarg($value) . " > /etc/timezone 2>&1 || echo 'Alpine timezone update failed'; fi", + "if [ -f /etc/sysconfig/clock ]; then sed -i 's/^ZONE=.*/ZONE=\"" . escapeshellarg($value) . "\"/' /etc/sysconfig/clock 2>&1 || echo '/etc/sysconfig/clock update failed'; fi", + "date +%Z", + "cat /etc/timezone 2>/dev/null || echo 'Unable to read /etc/timezone'", + ]; + + $result = instant_remote_process($commands, $this->server); + + if (!isset($result['output']) || empty($result['output'])) { + throw new \Exception("No output received from server. The timezone may not have been updated."); + } + + $output = is_array($result['output']) ? $result['output'] : explode("\n", trim($result['output'])); + $output = array_filter($output); // Remove empty lines + + if (count($output) < 2) { + throw new \Exception("Unexpected output format: " . implode("\n", $output)); + } + + $oldTimezone = $output[0]; + $newTimezone = end($output); + + $errors = array_filter($output, function($line) { + return strpos($line, 'failed') !== false; + }); + + if (!empty($errors)) { + throw new \Exception("Timezone change failed. Errors: " . implode(", ", $errors)); + } + + if ($oldTimezone === $newTimezone) { + throw new \Exception("Timezone change failed. The timezone is still set to {$oldTimezone}."); + } + $dateTime = new \DateTime('now', new \DateTimeZone($value)); $phpTimezone = $dateTime->getTimezone()->getName(); + + $this->server->settings->server_timezone = $phpTimezone; + $this->server->settings->save(); + + $this->dispatch('success', "Timezone successfully changed from {$oldTimezone} to {$newTimezone} (PHP: {$phpTimezone})."); + return true; } catch (\Exception $e) { - throw new \Exception("Invalid PHP timezone: {$value}. Error: " . $e->getMessage()); + $this->dispatch('error', $e->getMessage()); + return false; } - - $this->server->settings->server_timezone = $phpTimezone; - $this->server->settings->save(); - - return "Timezone successfully changed from {$oldTimezone} to {$newTimezone} (PHP: {$phpTimezone})."; } } \ No newline at end of file From 44f319460f42b6d727f8f8538a03b6d3f7ec978c Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 14 Aug 2024 23:29:33 +0200 Subject: [PATCH 08/42] remove unnecessary validation and fix safe to DB --- app/Livewire/Server/Form.php | 42 ++++++------------------------------ 1 file changed, 7 insertions(+), 35 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 318b0a8b4..c5ffcf974 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -243,6 +243,7 @@ class Form extends Component return; } $this->server->settings->server_timezone = $value; + $this->updateServerTimezone($value); } private function updateServerTimezone($value) @@ -260,42 +261,13 @@ class Form extends Component "date +%Z", "cat /etc/timezone 2>/dev/null || echo 'Unable to read /etc/timezone'", ]; - - $result = instant_remote_process($commands, $this->server); - - if (!isset($result['output']) || empty($result['output'])) { - throw new \Exception("No output received from server. The timezone may not have been updated."); - } - - $output = is_array($result['output']) ? $result['output'] : explode("\n", trim($result['output'])); - $output = array_filter($output); // Remove empty lines - - if (count($output) < 2) { - throw new \Exception("Unexpected output format: " . implode("\n", $output)); - } - - $oldTimezone = $output[0]; - $newTimezone = end($output); - - $errors = array_filter($output, function($line) { - return strpos($line, 'failed') !== false; - }); - - if (!empty($errors)) { - throw new \Exception("Timezone change failed. Errors: " . implode(", ", $errors)); - } - - if ($oldTimezone === $newTimezone) { - throw new \Exception("Timezone change failed. The timezone is still set to {$oldTimezone}."); - } - - $dateTime = new \DateTime('now', new \DateTimeZone($value)); - $phpTimezone = $dateTime->getTimezone()->getName(); - - $this->server->settings->server_timezone = $phpTimezone; + + instant_remote_process($commands, $this->server); + + $this->server->settings->server_timezone = $value; $this->server->settings->save(); - - $this->dispatch('success', "Timezone successfully changed from {$oldTimezone} to {$newTimezone} (PHP: {$phpTimezone})."); + + $this->dispatch('success', "Timezone successfully changed to {$value}."); return true; } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); From f0b9bd2cf2d540778b9d7f7daf0b7a9b01822461 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 00:31:23 +0200 Subject: [PATCH 09/42] set default time zone and remove success message --- app/Livewire/Server/Form.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index c5ffcf974..54cdf7a14 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -78,6 +78,11 @@ class Form extends Component $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); $this->wildcard_domain = $this->server->settings->wildcard_domain; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; + + if ($this->server->settings->server_timezone === '') { + $defaultTimezone = config('app.timezone'); + $this->updateServerTimezone($defaultTimezone); + } } public function serverInstalled() @@ -267,11 +272,10 @@ class Form extends Component $this->server->settings->server_timezone = $value; $this->server->settings->save(); - $this->dispatch('success', "Timezone successfully changed to {$value}."); return true; } catch (\Exception $e) { $this->dispatch('error', $e->getMessage()); return false; } } -} \ No newline at end of file +} From ef6cfd47c3205756b21eeea3a9321e77ef4d0f6a Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 00:51:45 +0200 Subject: [PATCH 10/42] add check if timezone was actually changed --- app/Livewire/Server/Form.php | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 54cdf7a14..daf21614b 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -267,15 +267,32 @@ class Form extends Component "cat /etc/timezone 2>/dev/null || echo 'Unable to read /etc/timezone'", ]; - instant_remote_process($commands, $this->server); - + ray('Commands to be executed:', $commands); + + $result = instant_remote_process($commands, $this->server); + ray('Result of instant_remote_process:', $result); + + // Check if the timezone was actually changed + $newTimezone = trim(instant_remote_process(["date +%Z"], $this->server, false)); + ray('New timezone after update:', $newTimezone); + + if ($newTimezone !== $value) { + ray('Timezone update failed. New timezone does not match requested value.'); + $this->dispatch('error', 'Failed to update server timezone. The server reported a different timezone than requested.'); + return false; + } + + ray('Updating server settings'); $this->server->settings->server_timezone = $value; $this->server->settings->save(); + ray('Server settings updated'); + ray('Timezone update completed successfully'); return true; } catch (\Exception $e) { - $this->dispatch('error', $e->getMessage()); + ray('Exception caught:', $e->getMessage()); + $this->dispatch('error', 'Failed to update server timezone: ' . $e->getMessage()); return false; } } -} +} \ No newline at end of file From 1376846077b73b288a1aeaf248ce79e841792801 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 12:04:06 +0200 Subject: [PATCH 11/42] fix: timezone not updated when systemd is missing --- app/Livewire/Server/Form.php | 44 ++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index daf21614b..0602dce07 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -6,6 +6,7 @@ use App\Actions\Server\StartSentinel; use App\Actions\Server\StopSentinel; use App\Jobs\PullSentinelImageJob; use App\Models\Server;; + use Livewire\Component; class Form extends Component @@ -78,9 +79,13 @@ class Form extends Component $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); $this->wildcard_domain = $this->server->settings->wildcard_domain; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; - + if ($this->server->settings->server_timezone === '') { + ray($this->server->settings->server_timezone); + ray('Server timezone is empty. Setting default timezone.'); + ray('Current timezone:', $this->server->settings->server_timezone); $defaultTimezone = config('app.timezone'); + ray('Default timezone:', $defaultTimezone); $this->updateServerTimezone($defaultTimezone); } } @@ -127,7 +132,6 @@ class Form extends Component } if ($this->server->settings->isDirty('is_server_api_enabled') && $this->server->settings->is_server_api_enabled === true) { ray('Starting sentinel'); - } } else { ray('Sentinel is not enabled'); @@ -167,7 +171,7 @@ class Form extends Component $this->server->settings->save(); $this->dispatch('proxyStatusUpdated'); } else { - $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.

Check this documentation for further help.

Error: '.$error); + $this->dispatch('error', 'Server is not reachable.', 'Please validate your configuration and connection.

Check this documentation for further help.

Error: ' . $error); return; } @@ -240,7 +244,7 @@ class Form extends Component $this->dispatch('success', 'Server updated.'); ray('Submit method completed'); } - + public function updatedServerTimezone($value) { if (!is_string($value) || !in_array($value, timezone_identifiers_list())) { @@ -251,20 +255,22 @@ class Form extends Component $this->updateServerTimezone($value); } - private function updateServerTimezone($value) + private function updateServerTimezone($desired_timezone) { - ray('updateServerTimezone called with value:', $value); + ray('updateServerTimezone called with value:', $desired_timezone); try { $commands = [ - "date +%Z", - "if command -v timedatectl >/dev/null 2>&1; then timedatectl set-timezone " . escapeshellarg($value) . " 2>&1 || echo 'timedatectl failed'; fi", - "if [ -f /etc/timezone ]; then echo " . escapeshellarg($value) . " > /etc/timezone 2>&1 || echo '/etc/timezone update failed'; fi", - "if [ -L /etc/localtime ] || [ -f /etc/localtime ]; then ln -sf /usr/share/zoneinfo/" . escapeshellarg($value) . " /etc/localtime 2>&1 || echo '/etc/localtime update failed'; fi", - "if command -v dpkg-reconfigure >/dev/null 2>&1; then dpkg-reconfigure -f noninteractive tzdata 2>&1 || echo 'dpkg-reconfigure failed'; fi", - "if command -v apk >/dev/null 2>&1; then apk add --no-cache tzdata 2>&1 && cp /usr/share/zoneinfo/" . escapeshellarg($value) . " /etc/localtime 2>&1 && echo " . escapeshellarg($value) . " > /etc/timezone 2>&1 || echo 'Alpine timezone update failed'; fi", - "if [ -f /etc/sysconfig/clock ]; then sed -i 's/^ZONE=.*/ZONE=\"" . escapeshellarg($value) . "\"/' /etc/sysconfig/clock 2>&1 || echo '/etc/sysconfig/clock update failed'; fi", - "date +%Z", - "cat /etc/timezone 2>/dev/null || echo 'Unable to read /etc/timezone'", + "if [ -f /etc/timezone ]; then", + " echo " . escapeshellarg($desired_timezone) . " > /etc/timezone", + " ln -sf /usr/share/zoneinfo/" . escapeshellarg($desired_timezone) . " /etc/localtime", + "elif [ -f /etc/localtime ]; then", + " ln -sf /usr/share/zoneinfo/" . escapeshellarg($desired_timezone) . " /etc/localtime", + "else", + " echo 'Unable to set timezone'", + " exit 1", + "fi", + "echo \"Timezone updated to: $desired_timezone\"", + "date" ]; ray('Commands to be executed:', $commands); @@ -273,17 +279,17 @@ class Form extends Component ray('Result of instant_remote_process:', $result); // Check if the timezone was actually changed - $newTimezone = trim(instant_remote_process(["date +%Z"], $this->server, false)); + $newTimezone = trim(instant_remote_process(["cat /etc/timezone 2>/dev/null || readlink /etc/localtime | sed 's#/usr/share/zoneinfo/##'"], $this->server, false)); ray('New timezone after update:', $newTimezone); - if ($newTimezone !== $value) { + if ($newTimezone !== $desired_timezone) { ray('Timezone update failed. New timezone does not match requested value.'); $this->dispatch('error', 'Failed to update server timezone. The server reported a different timezone than requested.'); return false; } ray('Updating server settings'); - $this->server->settings->server_timezone = $value; + $this->server->settings->server_timezone = $desired_timezone; $this->server->settings->save(); ray('Server settings updated'); @@ -295,4 +301,4 @@ class Form extends Component return false; } } -} \ No newline at end of file +} From a51b306c083f144b0ac0871219f0ea03fb374dae Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:13:52 +0200 Subject: [PATCH 12/42] support all coolify supported os and improve symbolic link creation --- app/Livewire/Server/Form.php | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 0602dce07..7f99375d1 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -260,15 +260,32 @@ class Form extends Component ray('updateServerTimezone called with value:', $desired_timezone); try { $commands = [ - "if [ -f /etc/timezone ]; then", + "if command -v timedatectl > /dev/null 2>&1 && pidof systemd > /dev/null; then", + " timedatectl set-timezone " . escapeshellarg($desired_timezone), + "elif [ -f /etc/timezone ]; then", " echo " . escapeshellarg($desired_timezone) . " > /etc/timezone", + " rm -f /etc/localtime", " ln -sf /usr/share/zoneinfo/" . escapeshellarg($desired_timezone) . " /etc/localtime", "elif [ -f /etc/localtime ]; then", + " rm -f /etc/localtime", " ln -sf /usr/share/zoneinfo/" . escapeshellarg($desired_timezone) . " /etc/localtime", "else", " echo 'Unable to set timezone'", " exit 1", "fi", + "if command -v dpkg-reconfigure > /dev/null 2>&1; then", + " dpkg-reconfigure -f noninteractive tzdata", + "elif command -v tzdata-update > /dev/null 2>&1; then", + " tzdata-update", + "elif [ -f /etc/sysconfig/clock ]; then", + " sed -i 's/^ZONE=.*/ZONE=\"" . $desired_timezone . "\"/' /etc/sysconfig/clock", + " source /etc/sysconfig/clock", + "fi", + "if command -v systemctl > /dev/null 2>&1 && pidof systemd > /dev/null; then", + " systemctl try-restart systemd-timesyncd.service || true", + "elif command -v service > /dev/null 2>&1; then", + " service ntpd restart || service ntp restart || true", + "fi", "echo \"Timezone updated to: $desired_timezone\"", "date" ]; @@ -279,7 +296,7 @@ class Form extends Component ray('Result of instant_remote_process:', $result); // Check if the timezone was actually changed - $newTimezone = trim(instant_remote_process(["cat /etc/timezone 2>/dev/null || readlink /etc/localtime | sed 's#/usr/share/zoneinfo/##'"], $this->server, false)); + $newTimezone = trim(instant_remote_process(["date +%Z"], $this->server, false)); ray('New timezone after update:', $newTimezone); if ($newTimezone !== $desired_timezone) { @@ -301,4 +318,4 @@ class Form extends Component return false; } } -} +} \ No newline at end of file From a1915e40f7a03f687a87be1a267f72a5169a8a66 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:25:30 +0200 Subject: [PATCH 13/42] new timezone validation and conversion to check --- app/Livewire/Server/Form.php | 50 ++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 13 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 7f99375d1..362f49803 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -295,27 +295,51 @@ class Form extends Component $result = instant_remote_process($commands, $this->server); ray('Result of instant_remote_process:', $result); - // Check if the timezone was actually changed - $newTimezone = trim(instant_remote_process(["date +%Z"], $this->server, false)); - ray('New timezone after update:', $newTimezone); - - if ($newTimezone !== $desired_timezone) { - ray('Timezone update failed. New timezone does not match requested value.'); - $this->dispatch('error', 'Failed to update server timezone. The server reported a different timezone than requested.'); + // Improved verification + $verificationCommands = [ + "date +'%Z %:z'", + "readlink /etc/localtime | sed 's#/usr/share/zoneinfo/##'", + ]; + $verificationResult = instant_remote_process($verificationCommands, $this->server, false); + $verificationLines = explode("\n", trim($verificationResult)); + + if (count($verificationLines) !== 2) { + ray('Unexpected verification result:', $verificationResult); + $this->dispatch('error', 'Failed to verify timezone update. Unexpected server response.'); return false; } - ray('Updating server settings'); - $this->server->settings->server_timezone = $desired_timezone; - $this->server->settings->save(); - ray('Server settings updated'); + [$abbreviation, $offset] = explode(' ', $verificationLines[0]); + $actualTimezone = trim($verificationLines[1]); - ray('Timezone update completed successfully'); - return true; + // Convert desired_timezone to DateTimeZone for comparison + $desiredTz = new \DateTimeZone($desired_timezone); + $desiredAbbr = (new \DateTime('now', $desiredTz))->format('T'); + $desiredOffset = $desiredTz->getOffset(new \DateTime('now', $desiredTz)); + + // Compare abbreviation, offset, and actual timezone + if ($abbreviation === $desiredAbbr && $offset === $this->formatOffset($desiredOffset) && $actualTimezone === $desired_timezone) { + ray('Timezone update verified successfully'); + $this->server->settings->server_timezone = $desired_timezone; + $this->server->settings->save(); + ray('Server settings updated'); + return true; + } else { + ray('Timezone verification failed. Expected:', $desired_timezone, 'Actual:', $actualTimezone); + $this->dispatch('error', 'Failed to update server timezone. The server reported a different timezone than requested.'); + return false; + } } catch (\Exception $e) { ray('Exception caught:', $e->getMessage()); $this->dispatch('error', 'Failed to update server timezone: ' . $e->getMessage()); return false; } } + + private function formatOffset($offsetSeconds) + { + $hours = abs($offsetSeconds) / 3600; + $minutes = (abs($offsetSeconds) % 3600) / 60; + return sprintf('%s%02d:%02d', $offsetSeconds >= 0 ? '+' : '-', $hours, $minutes); + } } \ No newline at end of file From 39b132f7e9ad204e469764e3aaec7e1274045723 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:30:08 +0200 Subject: [PATCH 14/42] verification compares to destination timezone --- app/Livewire/Server/Form.php | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 362f49803..15b235f1b 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -289,16 +289,16 @@ class Form extends Component "echo \"Timezone updated to: $desired_timezone\"", "date" ]; - + ray('Commands to be executed:', $commands); - + $result = instant_remote_process($commands, $this->server); ray('Result of instant_remote_process:', $result); - + // Improved verification $verificationCommands = [ - "date +'%Z %:z'", "readlink /etc/localtime | sed 's#/usr/share/zoneinfo/##'", + "date +'%Z %:z'" ]; $verificationResult = instant_remote_process($verificationCommands, $this->server, false); $verificationLines = explode("\n", trim($verificationResult)); @@ -308,17 +308,17 @@ class Form extends Component $this->dispatch('error', 'Failed to verify timezone update. Unexpected server response.'); return false; } - - [$abbreviation, $offset] = explode(' ', $verificationLines[0]); - $actualTimezone = trim($verificationLines[1]); - + + $actualTimezone = trim($verificationLines[0]); + [$abbreviation, $offset] = explode(' ', trim($verificationLines[1])); + // Convert desired_timezone to DateTimeZone for comparison $desiredTz = new \DateTimeZone($desired_timezone); $desiredAbbr = (new \DateTime('now', $desiredTz))->format('T'); - $desiredOffset = $desiredTz->getOffset(new \DateTime('now', $desiredTz)); - - // Compare abbreviation, offset, and actual timezone - if ($abbreviation === $desiredAbbr && $offset === $this->formatOffset($desiredOffset) && $actualTimezone === $desired_timezone) { + $desiredOffset = $this->formatOffset($desiredTz->getOffset(new \DateTime('now', $desiredTz))); + + // Compare actual timezone, abbreviation, and offset with the desired timezone + if ($actualTimezone === $desired_timezone && $abbreviation === $desiredAbbr && $offset === $desiredOffset) { ray('Timezone update verified successfully'); $this->server->settings->server_timezone = $desired_timezone; $this->server->settings->save(); @@ -326,6 +326,8 @@ class Form extends Component return true; } else { ray('Timezone verification failed. Expected:', $desired_timezone, 'Actual:', $actualTimezone); + ray('Expected abbreviation:', $desiredAbbr, 'Actual:', $abbreviation); + ray('Expected offset:', $desiredOffset, 'Actual:', $offset); $this->dispatch('error', 'Failed to update server timezone. The server reported a different timezone than requested.'); return false; } @@ -335,7 +337,7 @@ class Form extends Component return false; } } - + private function formatOffset($offsetSeconds) { $hours = abs($offsetSeconds) / 3600; From f281e9295487b12d771ee3d6e107394b7e629e44 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:36:17 +0200 Subject: [PATCH 15/42] remove ray --- app/Livewire/Server/Form.php | 50 ++++++------------------------------ 1 file changed, 8 insertions(+), 42 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 15b235f1b..a9277068c 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -81,11 +81,7 @@ class Form extends Component $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; if ($this->server->settings->server_timezone === '') { - ray($this->server->settings->server_timezone); - ray('Server timezone is empty. Setting default timezone.'); - ray('Current timezone:', $this->server->settings->server_timezone); $defaultTimezone = config('app.timezone'); - ray('Default timezone:', $defaultTimezone); $this->updateServerTimezone($defaultTimezone); } } @@ -187,7 +183,6 @@ class Form extends Component public function submit() { - ray('Submit method called'); if (isCloud() && !isDev()) { $this->validate(); $this->validate([ @@ -207,42 +202,27 @@ class Form extends Component $this->server->settings->wildcard_domain = $this->wildcard_domain; $this->server->settings->cleanup_after_percentage = $this->cleanup_after_percentage; - ray('Current timezone:', $this->server->settings->getOriginal('server_timezone')); - ray('New timezone:', $this->server->settings->server_timezone); - $currentTimezone = $this->server->settings->getOriginal('server_timezone'); $newTimezone = $this->server->settings->server_timezone; - ray('Comparing timezones:', $currentTimezone, $newTimezone); - if ($currentTimezone !== $newTimezone || $currentTimezone === '') { - ray('Timezone change detected'); try { - ray('Calling updateServerTimezone'); $timezoneUpdated = $this->updateServerTimezone($newTimezone); - ray('updateServerTimezone result:', $timezoneUpdated); if ($timezoneUpdated) { $this->server->settings->server_timezone = $newTimezone; $this->server->settings->save(); - ray('New timezone saved to database:', $newTimezone); } else { - ray('Timezone update failed'); return; } } catch (\Exception $e) { - ray('Exception in updateServerTimezone:', $e->getMessage()); $this->dispatch('error', 'Failed to update server timezone: ' . $e->getMessage()); return; } - } else { - ray('No timezone change detected'); } - ray('Saving server settings'); $this->server->settings->save(); $this->server->save(); $this->dispatch('success', 'Server updated.'); - ray('Submit method completed'); } public function updatedServerTimezone($value) @@ -257,7 +237,6 @@ class Form extends Component private function updateServerTimezone($desired_timezone) { - ray('updateServerTimezone called with value:', $desired_timezone); try { $commands = [ "if command -v timedatectl > /dev/null 2>&1 && pidof systemd > /dev/null; then", @@ -289,59 +268,46 @@ class Form extends Component "echo \"Timezone updated to: $desired_timezone\"", "date" ]; - - ray('Commands to be executed:', $commands); - + $result = instant_remote_process($commands, $this->server); - ray('Result of instant_remote_process:', $result); - - // Improved verification + $verificationCommands = [ "readlink /etc/localtime | sed 's#/usr/share/zoneinfo/##'", "date +'%Z %:z'" ]; $verificationResult = instant_remote_process($verificationCommands, $this->server, false); $verificationLines = explode("\n", trim($verificationResult)); - + if (count($verificationLines) !== 2) { - ray('Unexpected verification result:', $verificationResult); $this->dispatch('error', 'Failed to verify timezone update. Unexpected server response.'); return false; } - + $actualTimezone = trim($verificationLines[0]); [$abbreviation, $offset] = explode(' ', trim($verificationLines[1])); - - // Convert desired_timezone to DateTimeZone for comparison + $desiredTz = new \DateTimeZone($desired_timezone); $desiredAbbr = (new \DateTime('now', $desiredTz))->format('T'); $desiredOffset = $this->formatOffset($desiredTz->getOffset(new \DateTime('now', $desiredTz))); - - // Compare actual timezone, abbreviation, and offset with the desired timezone + if ($actualTimezone === $desired_timezone && $abbreviation === $desiredAbbr && $offset === $desiredOffset) { - ray('Timezone update verified successfully'); $this->server->settings->server_timezone = $desired_timezone; $this->server->settings->save(); - ray('Server settings updated'); return true; } else { - ray('Timezone verification failed. Expected:', $desired_timezone, 'Actual:', $actualTimezone); - ray('Expected abbreviation:', $desiredAbbr, 'Actual:', $abbreviation); - ray('Expected offset:', $desiredOffset, 'Actual:', $offset); $this->dispatch('error', 'Failed to update server timezone. The server reported a different timezone than requested.'); return false; } } catch (\Exception $e) { - ray('Exception caught:', $e->getMessage()); $this->dispatch('error', 'Failed to update server timezone: ' . $e->getMessage()); return false; } } - + private function formatOffset($offsetSeconds) { $hours = abs($offsetSeconds) / 3600; $minutes = (abs($offsetSeconds) % 3600) / 60; return sprintf('%s%02d:%02d', $offsetSeconds >= 0 ? '+' : '-', $hours, $minutes); } -} \ No newline at end of file +} From a478ebef2ec562bb5caa29a9ad648adbb21def7b Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Thu, 15 Aug 2024 13:37:52 +0200 Subject: [PATCH 16/42] remove result var --- app/Livewire/Server/Form.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index a9277068c..fbd354e05 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -269,7 +269,7 @@ class Form extends Component "date" ]; - $result = instant_remote_process($commands, $this->server); + instant_remote_process($commands, $this->server); $verificationCommands = [ "readlink /etc/localtime | sed 's#/usr/share/zoneinfo/##'", From 1892ce4e123c4bbf35715a90bbdee1ea69920617 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 12:58:19 +0200 Subject: [PATCH 17/42] Feat: cron jobs are executed based on the server timezone --- app/Console/Kernel.php | 10 ++++++---- app/Jobs/ScheduledTaskJob.php | 8 +++++++- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index e8f213b16..f1b9bf3d4 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -139,10 +139,9 @@ class Kernel extends ConsoleKernel $service = $scheduled_task->service; $application = $scheduled_task->application; - if (! $application && ! $service) { + if (!$application && !$service) { ray('application/service attached to scheduled task does not exist'); $scheduled_task->delete(); - continue; } if ($application) { @@ -158,9 +157,12 @@ class Kernel extends ConsoleKernel if (isset(VALID_CRON_STRINGS[$scheduled_task->frequency])) { $scheduled_task->frequency = VALID_CRON_STRINGS[$scheduled_task->frequency]; } + $server_timezone = $application ? $application->destination->server->settings->server_timezone : $service->destination->server->settings->server_timezone; + $server_timezone = $server_timezone; + ray($server_timezone); $schedule->job(new ScheduledTaskJob( task: $scheduled_task - ))->cron($scheduled_task->frequency)->onOneServer(); + ))->cron($scheduled_task->frequency)->timezone($server_timezone)->onOneServer(); } } @@ -170,4 +172,4 @@ class Kernel extends ConsoleKernel require base_path('routes/console.php'); } -} +} \ No newline at end of file diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php index 819e28f89..2e8bf4015 100644 --- a/app/Jobs/ScheduledTaskJob.php +++ b/app/Jobs/ScheduledTaskJob.php @@ -36,6 +36,8 @@ class ScheduledTaskJob implements ShouldQueue public array $containers = []; + public string $server_timezone; + public function __construct($task) { $this->task = $task; @@ -47,6 +49,7 @@ class ScheduledTaskJob implements ShouldQueue throw new \RuntimeException('ScheduledTaskJob failed: No resource found.'); } $this->team = Team::find($task->team_id); + $this->server_timezone = $this->resource->destination->server->settings->server_timezone; } public function middleware(): array @@ -61,6 +64,7 @@ class ScheduledTaskJob implements ShouldQueue public function handle(): void { + try { $this->task_log = ScheduledTaskExecution::create([ 'scheduled_task_id' => $this->task->id, @@ -121,6 +125,8 @@ class ScheduledTaskJob implements ShouldQueue $this->team?->notify(new TaskFailed($this->task, $e->getMessage())); // send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage()); throw $e; + } finally { + } } -} +} \ No newline at end of file From ea4b085dbe082f75070e8db1fc2caaf847785334 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 13:04:44 +0200 Subject: [PATCH 18/42] add server timezone to every schedule --- app/Console/Kernel.php | 73 ++++++++++++++++++++++-------------------- 1 file changed, 39 insertions(+), 34 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index f1b9bf3d4..8cfcb0168 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -30,62 +30,70 @@ class Kernel extends ConsoleKernel $this->all_servers = Server::all(); $settings = InstanceSettings::get(); + $serverTimezone = $this->getServerTimezone(); + if (isDev()) { // Instance Jobs - $schedule->command('horizon:snapshot')->everyMinute(); - $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer(); + $schedule->command('horizon:snapshot')->everyMinute()->timezone($serverTimezone); + $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer()->timezone($serverTimezone); // Server Jobs - $this->check_scheduled_backups($schedule); - $this->check_resources($schedule); - $this->check_scheduled_tasks($schedule); - $schedule->command('uploads:clear')->everyTwoMinutes(); + $this->check_scheduled_backups($schedule, $serverTimezone); + $this->check_resources($schedule, $serverTimezone); + $this->check_scheduled_tasks($schedule, $serverTimezone); + $schedule->command('uploads:clear')->everyTwoMinutes()->timezone($serverTimezone); } else { // Instance Jobs - $schedule->command('horizon:snapshot')->everyFiveMinutes(); - $schedule->command('cleanup:unreachable-servers')->daily(); - $schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->onOneServer(); - $schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->onOneServer(); - $schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer(); - $this->schedule_updates($schedule); + $schedule->command('horizon:snapshot')->everyFiveMinutes()->timezone($serverTimezone); + $schedule->command('cleanup:unreachable-servers')->daily()->timezone($serverTimezone); + $schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); + $schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); + $schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer()->timezone($serverTimezone); + $this->schedule_updates($schedule, $serverTimezone); // Server Jobs - $this->check_scheduled_backups($schedule); - $this->check_resources($schedule); - $this->pull_images($schedule); - $this->check_scheduled_tasks($schedule); + $this->check_scheduled_backups($schedule, $serverTimezone); + $this->check_resources($schedule, $serverTimezone); + $this->pull_images($schedule, $serverTimezone); + $this->check_scheduled_tasks($schedule, $serverTimezone); - $schedule->command('cleanup:database --yes')->daily(); - $schedule->command('uploads:clear')->everyTwoMinutes(); + $schedule->command('cleanup:database --yes')->daily()->timezone($serverTimezone); + $schedule->command('uploads:clear')->everyTwoMinutes()->timezone($serverTimezone); } } - private function pull_images($schedule) + private function getServerTimezone() + { + $server = Server::find(0); // Only main server is used for scheduling tasks, not each server timezone? + return $server->settings->server_timezone; + } + + private function pull_images($schedule, $serverTimezone) { $settings = InstanceSettings::get(); $servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4'); foreach ($servers as $server) { if ($server->isSentinelEnabled()) { - $schedule->job(new PullSentinelImageJob($server))->cron($settings->update_check_frequency)->onOneServer(); + $schedule->job(new PullSentinelImageJob($server))->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); } - $schedule->job(new PullHelperImageJob($server))->cron($settings->update_check_frequency)->onOneServer(); + $schedule->job(new PullHelperImageJob($server))->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); } } - private function schedule_updates($schedule) + private function schedule_updates($schedule, $serverTimezone) { $settings = InstanceSettings::get(); $updateCheckFrequency = $settings->update_check_frequency; - $schedule->job(new CheckForUpdatesJob)->cron($updateCheckFrequency)->onOneServer(); + $schedule->job(new CheckForUpdatesJob)->cron($updateCheckFrequency)->onOneServer()->timezone($serverTimezone); if ($settings->is_auto_update_enabled) { $autoUpdateFrequency = $settings->auto_update_frequency; - $schedule->job(new UpdateCoolifyJob)->cron($autoUpdateFrequency)->onOneServer(); + $schedule->job(new UpdateCoolifyJob)->cron($autoUpdateFrequency)->onOneServer()->timezone($serverTimezone); } } - private function check_resources($schedule) + private function check_resources($schedule, $serverTimezone) { if (isCloud()) { $servers = $this->all_servers->whereNotNull('team.subscription')->where('team.subscription.stripe_trial_already_ended', false)->where('ip', '!=', '1.2.3.4'); @@ -95,12 +103,12 @@ class Kernel extends ConsoleKernel $servers = $this->all_servers->where('ip', '!=', '1.2.3.4'); } foreach ($servers as $server) { - $schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer(); - $schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->onOneServer(); + $schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer()->timezone($serverTimezone); + $schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->onOneServer()->timezone($serverTimezone); } } - private function check_scheduled_backups($schedule) + private function check_scheduled_backups($schedule, $serverTimezone) { $scheduled_backups = ScheduledDatabaseBackup::all(); if ($scheduled_backups->isEmpty()) { @@ -122,11 +130,11 @@ class Kernel extends ConsoleKernel } $schedule->job(new DatabaseBackupJob( backup: $scheduled_backup - ))->cron($scheduled_backup->frequency)->onOneServer(); + ))->cron($scheduled_backup->frequency)->onOneServer()->timezone($serverTimezone); } } - private function check_scheduled_tasks($schedule) + private function check_scheduled_tasks($schedule, $serverTimezone) { $scheduled_tasks = ScheduledTask::all(); if ($scheduled_tasks->isEmpty()) { @@ -157,12 +165,9 @@ class Kernel extends ConsoleKernel if (isset(VALID_CRON_STRINGS[$scheduled_task->frequency])) { $scheduled_task->frequency = VALID_CRON_STRINGS[$scheduled_task->frequency]; } - $server_timezone = $application ? $application->destination->server->settings->server_timezone : $service->destination->server->settings->server_timezone; - $server_timezone = $server_timezone; - ray($server_timezone); $schedule->job(new ScheduledTaskJob( task: $scheduled_task - ))->cron($scheduled_task->frequency)->timezone($server_timezone)->onOneServer(); + ))->cron($scheduled_task->frequency)->timezone($serverTimezone)->onOneServer(); } } From e3b988424711ee61fe60d658783497d57f61f011 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 14:45:40 +0200 Subject: [PATCH 19/42] UI fix --- .../Shared/ScheduledTask/Executions.php | 12 +++++++++-- .../scheduled-task/executions.blade.php | 20 +++++++++++++++++-- .../shared/scheduled-task/show.blade.php | 4 ++-- 3 files changed, 30 insertions(+), 6 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Executions.php b/app/Livewire/Project/Shared/ScheduledTask/Executions.php index 7a2e14e89..3ee053e3e 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Executions.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Executions.php @@ -7,8 +7,8 @@ use Livewire\Component; class Executions extends Component { public $executions = []; - public $selectedKey; + public $task; public function getListeners() { @@ -26,4 +26,12 @@ class Executions extends Component } $this->selectedKey = $key; } -} + + public function getServerTimezone() + { + $server = data_get($this, 'destination.server'); + $serverTimezone = $server->settings->server_timezone; + ray('Server Timezone:', $serverTimezone); + return $serverTimezone; + } +} \ No newline at end of file diff --git a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php index afbf1ea93..cf7a591d7 100644 --- a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php @@ -24,9 +24,25 @@
@endif
Status: {{ data_get($execution, 'status') }}
-
Started At: {{ data_get($execution, 'created_at') }}
+
Started At: + @php + $createdAt = data_get($execution, 'created_at', now()); + $serverTimezone = $this->getServerTimezone(); + ray('Created At:', $createdAt, 'Server Timezone:', $serverTimezone); + + $date = new DateTime($createdAt); + if ($serverTimezone) { + try { + $date->setTimezone(new DateTimeZone($serverTimezone)); + } catch (\Exception $e) { + ray('Invalid timezone:', $serverTimezone); + } + } + echo $date->format('Y-m-d H:i:s T'); + @endphp +
@empty
No executions found.
@endforelse -
+
\ No newline at end of file diff --git a/resources/views/livewire/project/shared/scheduled-task/show.blade.php b/resources/views/livewire/project/shared/scheduled-task/show.blade.php index b69463a0e..d448000ca 100644 --- a/resources/views/livewire/project/shared/scheduled-task/show.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/show.blade.php @@ -42,6 +42,6 @@

Recent executions (click to check output)

- +
-
+
\ No newline at end of file From 1e711de52a9548cf7697c1dde093a9e8f1c21a7a Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 15:58:33 +0200 Subject: [PATCH 20/42] UI for Instance timezone --- .../views/livewire/settings/index.blade.php | 33 ++++++++++++++++++- 1 file changed, 32 insertions(+), 1 deletion(-) diff --git a/resources/views/livewire/settings/index.blade.php b/resources/views/livewire/settings/index.blade.php index d53db6a98..93c233b6a 100644 --- a/resources/views/livewire/settings/index.blade.php +++ b/resources/views/livewire/settings/index.blade.php @@ -17,6 +17,37 @@

Instance Settings

+
+ +
+ +
+ +
+
+

DNS Validation

@@ -71,4 +102,4 @@
- + \ No newline at end of file From d906bb2381916582c7f52bb94640b4e41c64e6fb Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:00:30 +0200 Subject: [PATCH 21/42] new DB migration for instance timezone --- ...mezone_to_server_and_instance_settings.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 database/migrations/2024_08_12_155023_add_timezone_to_server_and_instance_settings.php diff --git a/database/migrations/2024_08_12_155023_add_timezone_to_server_and_instance_settings.php b/database/migrations/2024_08_12_155023_add_timezone_to_server_and_instance_settings.php new file mode 100644 index 000000000..5bc73a54e --- /dev/null +++ b/database/migrations/2024_08_12_155023_add_timezone_to_server_and_instance_settings.php @@ -0,0 +1,30 @@ +string('server_timezone')->default(''); + }); + + Schema::table('instance_settings', function (Blueprint $table) { + $table->string('instance_timezone')->default('UTC'); + }); + } + + public function down() + { + Schema::table('server_settings', function (Blueprint $table) { + $table->dropColumn('server_timezone'); + }); + + Schema::table('instance_settings', function (Blueprint $table) { + $table->dropColumn('instance_timezone'); + }); + } +} From dab5f0fe093dafcdcdf701954c39268bcdf24256 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:01:41 +0200 Subject: [PATCH 22/42] add logic --- app/Console/Kernel.php | 96 +++++++++++++++----------- app/Jobs/ScheduledTaskJob.php | 11 ++- app/Models/ScheduledDatabaseBackup.php | 20 +++++- app/Models/ScheduledTask.php | 14 +++- 4 files changed, 97 insertions(+), 44 deletions(-) diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 8cfcb0168..3140de52c 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -30,70 +30,74 @@ class Kernel extends ConsoleKernel $this->all_servers = Server::all(); $settings = InstanceSettings::get(); - $serverTimezone = $this->getServerTimezone(); - if (isDev()) { // Instance Jobs - $schedule->command('horizon:snapshot')->everyMinute()->timezone($serverTimezone); - $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer()->timezone($serverTimezone); + $schedule->command('horizon:snapshot')->everyMinute(); + $schedule->job(new CleanupInstanceStuffsJob)->everyMinute()->onOneServer(); // Server Jobs - $this->check_scheduled_backups($schedule, $serverTimezone); - $this->check_resources($schedule, $serverTimezone); - $this->check_scheduled_tasks($schedule, $serverTimezone); - $schedule->command('uploads:clear')->everyTwoMinutes()->timezone($serverTimezone); + $this->check_scheduled_backups($schedule); + $this->check_resources($schedule); + $this->check_scheduled_tasks($schedule); + $schedule->command('uploads:clear')->everyTwoMinutes(); } else { // Instance Jobs - $schedule->command('horizon:snapshot')->everyFiveMinutes()->timezone($serverTimezone); - $schedule->command('cleanup:unreachable-servers')->daily()->timezone($serverTimezone); - $schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); - $schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); - $schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer()->timezone($serverTimezone); - $this->schedule_updates($schedule, $serverTimezone); + $schedule->command('horizon:snapshot')->everyFiveMinutes(); + $schedule->command('cleanup:unreachable-servers')->daily(); + $schedule->job(new PullCoolifyImageJob)->cron($settings->update_check_frequency)->timezone($settings->instance_timezone)->onOneServer(); + $schedule->job(new PullTemplatesFromCDN)->cron($settings->update_check_frequency)->timezone($settings->instance_timezone)->onOneServer(); + $schedule->job(new CleanupInstanceStuffsJob)->everyTwoMinutes()->onOneServer(); + $this->schedule_updates($schedule); // Server Jobs - $this->check_scheduled_backups($schedule, $serverTimezone); - $this->check_resources($schedule, $serverTimezone); - $this->pull_images($schedule, $serverTimezone); - $this->check_scheduled_tasks($schedule, $serverTimezone); + $this->check_scheduled_backups($schedule); + $this->check_resources($schedule); + $this->pull_images($schedule); + $this->check_scheduled_tasks($schedule); - $schedule->command('cleanup:database --yes')->daily()->timezone($serverTimezone); - $schedule->command('uploads:clear')->everyTwoMinutes()->timezone($serverTimezone); + $schedule->command('cleanup:database --yes')->daily(); + $schedule->command('uploads:clear')->everyTwoMinutes(); } } - private function getServerTimezone() - { - $server = Server::find(0); // Only main server is used for scheduling tasks, not each server timezone? - return $server->settings->server_timezone; - } - - private function pull_images($schedule, $serverTimezone) + private function pull_images($schedule) { $settings = InstanceSettings::get(); $servers = $this->all_servers->where('settings.is_usable', true)->where('settings.is_reachable', true)->where('ip', '!=', '1.2.3.4'); foreach ($servers as $server) { if ($server->isSentinelEnabled()) { - $schedule->job(new PullSentinelImageJob($server))->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); + $schedule->job(new PullSentinelImageJob($server)) + ->cron($settings->update_check_frequency) + ->timezone($settings->instance_timezone) + ->onOneServer(); } - $schedule->job(new PullHelperImageJob($server))->cron($settings->update_check_frequency)->onOneServer()->timezone($serverTimezone); + $schedule->job(new PullHelperImageJob($server)) + ->cron($settings->update_check_frequency) + ->timezone($settings->instance_timezone) + ->onOneServer(); } } - private function schedule_updates($schedule, $serverTimezone) + private function schedule_updates($schedule) { $settings = InstanceSettings::get(); $updateCheckFrequency = $settings->update_check_frequency; - $schedule->job(new CheckForUpdatesJob)->cron($updateCheckFrequency)->onOneServer()->timezone($serverTimezone); + $schedule->job(new CheckForUpdatesJob) + ->cron($updateCheckFrequency) + ->timezone($settings->instance_timezone) + ->onOneServer(); if ($settings->is_auto_update_enabled) { $autoUpdateFrequency = $settings->auto_update_frequency; - $schedule->job(new UpdateCoolifyJob)->cron($autoUpdateFrequency)->onOneServer()->timezone($serverTimezone); + $schedule->job(new UpdateCoolifyJob) + ->cron($autoUpdateFrequency) + ->timezone($settings->instance_timezone) + ->onOneServer(); } } - private function check_resources($schedule, $serverTimezone) + private function check_resources($schedule) { if (isCloud()) { $servers = $this->all_servers->whereNotNull('team.subscription')->where('team.subscription.stripe_trial_already_ended', false)->where('ip', '!=', '1.2.3.4'); @@ -103,12 +107,16 @@ class Kernel extends ConsoleKernel $servers = $this->all_servers->where('ip', '!=', '1.2.3.4'); } foreach ($servers as $server) { - $schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer()->timezone($serverTimezone); - $schedule->job(new DockerCleanupJob($server))->everyTenMinutes()->onOneServer()->timezone($serverTimezone); + $schedule->job(new ServerCheckJob($server))->everyMinute()->onOneServer(); + $serverTimezone = $server->settings->server_timezone; + $schedule->job(new DockerCleanupJob($server)) + ->everyTenMinutes() //will be changed in the second PR + ->timezone($serverTimezone) + ->onOneServer(); } } - private function check_scheduled_backups($schedule, $serverTimezone) + private function check_scheduled_backups($schedule) { $scheduled_backups = ScheduledDatabaseBackup::all(); if ($scheduled_backups->isEmpty()) { @@ -121,20 +129,22 @@ class Kernel extends ConsoleKernel if (is_null(data_get($scheduled_backup, 'database'))) { ray('database not found'); $scheduled_backup->delete(); - continue; } + $server = $scheduled_backup->server(); + $serverTimezone = $server->settings->server_timezone; + if (isset(VALID_CRON_STRINGS[$scheduled_backup->frequency])) { $scheduled_backup->frequency = VALID_CRON_STRINGS[$scheduled_backup->frequency]; } $schedule->job(new DatabaseBackupJob( backup: $scheduled_backup - ))->cron($scheduled_backup->frequency)->onOneServer()->timezone($serverTimezone); + ))->cron($scheduled_backup->frequency)->timezone($serverTimezone)->onOneServer(); } } - private function check_scheduled_tasks($schedule, $serverTimezone) + private function check_scheduled_tasks($schedule) { $scheduled_tasks = ScheduledTask::all(); if ($scheduled_tasks->isEmpty()) { @@ -147,7 +157,7 @@ class Kernel extends ConsoleKernel $service = $scheduled_task->service; $application = $scheduled_task->application; - if (!$application && !$service) { + if (! $application && ! $service) { ray('application/service attached to scheduled task does not exist'); $scheduled_task->delete(); continue; @@ -162,6 +172,10 @@ class Kernel extends ConsoleKernel continue; } } + + $server = $scheduled_task->server(); + $serverTimezone = $server->settings->server_timezone ?: config('app.timezone'); + if (isset(VALID_CRON_STRINGS[$scheduled_task->frequency])) { $scheduled_task->frequency = VALID_CRON_STRINGS[$scheduled_task->frequency]; } @@ -173,7 +187,7 @@ class Kernel extends ConsoleKernel protected function commands(): void { - $this->load(__DIR__.'/Commands'); + $this->load(__DIR__ . '/Commands'); require base_path('routes/console.php'); } diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php index 2e8bf4015..3daaa9e83 100644 --- a/app/Jobs/ScheduledTaskJob.php +++ b/app/Jobs/ScheduledTaskJob.php @@ -49,7 +49,16 @@ class ScheduledTaskJob implements ShouldQueue throw new \RuntimeException('ScheduledTaskJob failed: No resource found.'); } $this->team = Team::find($task->team_id); - $this->server_timezone = $this->resource->destination->server->settings->server_timezone; + $this->server_timezone = $this->getServerTimezone(); + } + + private function getServerTimezone(): string + { + if ($this->resource instanceof Application) { + return $this->resource->destination->server->settings->server_timezone; + } elseif ($this->resource instanceof Service) { + return $this->resource->server->settings->server_timezone; + } } public function middleware(): array diff --git a/app/Models/ScheduledDatabaseBackup.php b/app/Models/ScheduledDatabaseBackup.php index edd840e7d..a512a3f5f 100644 --- a/app/Models/ScheduledDatabaseBackup.php +++ b/app/Models/ScheduledDatabaseBackup.php @@ -34,4 +34,22 @@ class ScheduledDatabaseBackup extends BaseModel { return $this->hasMany(ScheduledDatabaseBackupExecution::class)->where('created_at', '>=', now()->subDays($days))->get(); } -} + + public function server() + { + $database = $this->database; + if (!$database) { + return null; + } + + if (method_exists($database, 'server')) { + return $database->server; + } + + if (method_exists($database, 'service') && $database->service) { + return $database->service->server; + } + + return null; + } +} \ No newline at end of file diff --git a/app/Models/ScheduledTask.php b/app/Models/ScheduledTask.php index 1cb805e8e..35b00873e 100644 --- a/app/Models/ScheduledTask.php +++ b/app/Models/ScheduledTask.php @@ -28,4 +28,16 @@ class ScheduledTask extends BaseModel { return $this->hasMany(ScheduledTaskExecution::class); } -} + + public function server() + { + if ($this->application) { + return $this->application->server; + } elseif ($this->database) { + return $this->database->server; + } elseif ($this->service) { + return $this->service->server; + } + return null; + } +} \ No newline at end of file From 883a52afe985650a95043beb2acb798d4df98d36 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:01:57 +0200 Subject: [PATCH 23/42] show cron execution with timezone --- .../Shared/ScheduledTask/Executions.php | 21 +++++++++++++++++-- app/Livewire/Settings/Index.php | 6 +++++- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Executions.php b/app/Livewire/Project/Shared/ScheduledTask/Executions.php index 3ee053e3e..0f26523cb 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Executions.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Executions.php @@ -27,11 +27,28 @@ class Executions extends Component $this->selectedKey = $key; } + public function server() + { + return $this->destination->server; + } + public function getServerTimezone() { - $server = data_get($this, 'destination.server'); - $serverTimezone = $server->settings->server_timezone; + $server = $this->server(); + $serverTimezone = $server->settings->server_timezone ?: config('app.timezone'); ray('Server Timezone:', $serverTimezone); return $serverTimezone; } + + public function formatDateInServerTimezone($date) + { + $serverTimezone = $this->getServerTimezone(); + $dateObj = new \DateTime($date); + try { + $dateObj->setTimezone(new \DateTimeZone($serverTimezone)); + } catch (\Exception $e) { + ray('Invalid timezone:', $serverTimezone); + } + return $dateObj->format('Y-m-d H:i:s T'); + } } \ No newline at end of file diff --git a/app/Livewire/Settings/Index.php b/app/Livewire/Settings/Index.php index f593fb78b..eff09f0e5 100644 --- a/app/Livewire/Settings/Index.php +++ b/app/Livewire/Settings/Index.php @@ -40,6 +40,7 @@ class Index extends Component 'settings.is_auto_update_enabled' => 'boolean', 'auto_update_frequency' => 'string', 'update_check_frequency' => 'string', + 'settings.instance_timezone' => 'required|string|timezone', ]; protected $validationAttributes = [ @@ -54,6 +55,8 @@ class Index extends Component 'update_check_frequency' => 'Update Check Frequency', ]; + public $timezones; + public function mount() { if (isInstanceAdmin()) { @@ -65,6 +68,7 @@ class Index extends Component $this->is_api_enabled = $this->settings->is_api_enabled; $this->auto_update_frequency = $this->settings->auto_update_frequency; $this->update_check_frequency = $this->settings->update_check_frequency; + $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); } else { return redirect()->route('dashboard'); } @@ -170,4 +174,4 @@ class Index extends Component { return view('livewire.settings.index'); } -} +} \ No newline at end of file From 4a476586dfd368b295a5e5c7bb6e51a029432f72 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:02:07 +0200 Subject: [PATCH 24/42] remove old DB migration --- ..._add_timezone_to_server_settings_table.php | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php diff --git a/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php b/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php deleted file mode 100644 index 62511ffb3..000000000 --- a/database/migrations/2024_08_12_155023_add_timezone_to_server_settings_table.php +++ /dev/null @@ -1,22 +0,0 @@ -string('server_timezone')->default(''); - }); - } - - public function down() - { - Schema::table('server_settings', function (Blueprint $table) { - $table->dropColumn('server_timezone'); - }); - } -} \ No newline at end of file From 7b4182352d9fe6339dc31abb1b978e89a8247bce Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:02:25 +0200 Subject: [PATCH 25/42] UI executions with TZ --- .../shared/scheduled-task/executions.blade.php | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php index cf7a591d7..1129b4b11 100644 --- a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php @@ -25,21 +25,7 @@ @endif
Status: {{ data_get($execution, 'status') }}
Started At: - @php - $createdAt = data_get($execution, 'created_at', now()); - $serverTimezone = $this->getServerTimezone(); - ray('Created At:', $createdAt, 'Server Timezone:', $serverTimezone); - - $date = new DateTime($createdAt); - if ($serverTimezone) { - try { - $date->setTimezone(new DateTimeZone($serverTimezone)); - } catch (\Exception $e) { - ray('Invalid timezone:', $serverTimezone); - } - } - echo $date->format('Y-m-d H:i:s T'); - @endphp + {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at', now())) }}
@empty From fda6c03505f173a0c5cfd607777e83e273e4b708 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:18:33 +0200 Subject: [PATCH 26/42] get server correctly for scheduled tasks --- app/Models/ScheduledTask.php | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/Models/ScheduledTask.php b/app/Models/ScheduledTask.php index 35b00873e..c01e5e057 100644 --- a/app/Models/ScheduledTask.php +++ b/app/Models/ScheduledTask.php @@ -31,13 +31,26 @@ class ScheduledTask extends BaseModel public function server() { + ray('Entering server() method in ScheduledTask model'); + if ($this->application) { - return $this->application->server; + ray('Returning server from application'); + $server = $this->application->server; + ray('Returning server from application: '.$server); + return $server; } elseif ($this->database) { - return $this->database->server; + ray('Returning server from database'); + $server = $this->database->server; + ray('Returning server from database: '.$server); + return $server; } elseif ($this->service) { - return $this->service->server; + ray('Returning server from service'); + $server = $this->service->server; + ray('Returning server from service: '.$server); + return $server; } + + ray('No server found, returning null'); return null; } } \ No newline at end of file From 6242243ced132621fcc549be9584e9326d7a6ae1 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 16:18:57 +0200 Subject: [PATCH 27/42] get timezone and server correctly for UI --- .../Shared/ScheduledTask/Executions.php | 29 +++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Executions.php b/app/Livewire/Project/Shared/ScheduledTask/Executions.php index 0f26523cb..16bc7bc5b 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Executions.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Executions.php @@ -29,13 +29,36 @@ class Executions extends Component public function server() { - return $this->destination->server; + ray('Entering server() In UI'); + + if (!$this->task) { + ray('No task found, returning null'); + return null; + } + + if ($this->task->application) { + ray('Returning server from application'); + return $this->task->application->server; + } elseif ($this->task->database) { + ray('Returning server from database'); + return $this->task->database->server; + } elseif ($this->task->service) { + ray('Returning server from service'); + return $this->task->service->server; + } + + ray('No server found, returning null'); + return null; } public function getServerTimezone() { $server = $this->server(); - $serverTimezone = $server->settings->server_timezone ?: config('app.timezone'); + if (!$server) { + ray('No server found, returning default timezone'); + return 'UTC'; + } + $serverTimezone = $server->settings->server_timezone ?? 'UTC'; ray('Server Timezone:', $serverTimezone); return $serverTimezone; } @@ -48,6 +71,8 @@ class Executions extends Component $dateObj->setTimezone(new \DateTimeZone($serverTimezone)); } catch (\Exception $e) { ray('Invalid timezone:', $serverTimezone); + // Fallback to UTC + $dateObj->setTimezone(new \DateTimeZone('UTC')); } return $dateObj->format('Y-m-d H:i:s T'); } From 00f20c708f5598a87849375aaa6a38dfb24b3417 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:09:30 +0200 Subject: [PATCH 28/42] remove mount default timezone --- app/Livewire/Server/Form.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index fbd354e05..55b81fdde 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -80,10 +80,10 @@ class Form extends Component $this->wildcard_domain = $this->server->settings->wildcard_domain; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; - if ($this->server->settings->server_timezone === '') { - $defaultTimezone = config('app.timezone'); - $this->updateServerTimezone($defaultTimezone); - } + // if ($this->server->settings->server_timezone === '') { + // $defaultTimezone = config('app.timezone'); + // $this->updateServerTimezone($defaultTimezone); + // } } public function serverInstalled() @@ -235,7 +235,7 @@ class Form extends Component $this->updateServerTimezone($value); } - private function updateServerTimezone($desired_timezone) + public function updateServerTimezone($desired_timezone) { try { $commands = [ From 3e3b92638bfa2c7c00848d1acb6d9c7a81cb4dea Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:09:53 +0200 Subject: [PATCH 29/42] Add: server timezone seeder --- database/seeders/DatabaseSeeder.php | 1 + database/seeders/ProductionSeeder.php | 6 +++- database/seeders/ServerTimezoneSeeder.php | 38 +++++++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 database/seeders/ServerTimezoneSeeder.php diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index b3fac350f..736646ec6 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -33,6 +33,7 @@ class DatabaseSeeder extends Seeder ScheduledDatabaseBackupSeeder::class, ScheduledDatabaseBackupExecutionSeeder::class, OauthSettingSeeder::class, + ServerTimezoneSeeder::class, ]); } } diff --git a/database/seeders/ProductionSeeder.php b/database/seeders/ProductionSeeder.php index c88a35f6a..a3bdab536 100644 --- a/database/seeders/ProductionSeeder.php +++ b/database/seeders/ProductionSeeder.php @@ -79,7 +79,8 @@ class ProductionSeeder extends Seeder ], [ 'name' => 'localhost\'s key', - 'description' => 'The private key for the Coolify host machine (localhost).', 'private_key' => $coolify_key, + 'description' => 'The private key for the Coolify host machine (localhost).', + 'private_key' => $coolify_key, ] ); } else { @@ -180,5 +181,8 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== $oauth_settings_seeder = new OauthSettingSeeder; $oauth_settings_seeder->run(); + + $server_timezone_seeder = new ServerTimezoneSeeder; + $server_timezone_seeder->run(); } } diff --git a/database/seeders/ServerTimezoneSeeder.php b/database/seeders/ServerTimezoneSeeder.php new file mode 100644 index 000000000..fc31eb761 --- /dev/null +++ b/database/seeders/ServerTimezoneSeeder.php @@ -0,0 +1,38 @@ +whereNull('server_timezone')->orWhere('server_timezone', ''); + })->each(function ($server) use ($defaultTimezone) { + DB::transaction(function () use ($server, $defaultTimezone) { + $server->settings->server_timezone = $defaultTimezone; + $server->settings->save(); + + $formComponent = new Form(); + $formComponent->server = $server; + $formComponent->updateServerTimezone($defaultTimezone); + + // Refresh the server settings to ensure we have the latest data + $server->settings->refresh(); + + // Double-check and set the timezone if it's still not set + if (!$server->settings->server_timezone) { + $server->settings->server_timezone = $defaultTimezone; + $server->settings->save(); + } + }); + }); + } +} From 74bf4629d6c566c1fceb6647152e2c10cf7b6661 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:42:26 +0200 Subject: [PATCH 30/42] added helpers to the timezone switcher --- resources/views/livewire/server/form.blade.php | 5 ++++- resources/views/livewire/settings/index.blade.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index 635e5e316..b26122e57 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -78,7 +78,10 @@ }) } }"> - +
+ + +
Date: Fri, 16 Aug 2024 17:43:14 +0200 Subject: [PATCH 31/42] fixed database seeder, remove dependency on form.php --- database/seeders/ServerTimezoneSeeder.php | 52 ++++++++++++++++------- 1 file changed, 36 insertions(+), 16 deletions(-) diff --git a/database/seeders/ServerTimezoneSeeder.php b/database/seeders/ServerTimezoneSeeder.php index fc31eb761..9dd6636f9 100644 --- a/database/seeders/ServerTimezoneSeeder.php +++ b/database/seeders/ServerTimezoneSeeder.php @@ -4,9 +4,9 @@ namespace Database\Seeders; use App\Models\Server; use Illuminate\Database\Seeder; -use App\Livewire\Server\Form; use Illuminate\Support\Facades\DB; + class ServerTimezoneSeeder extends Seeder { public function run(): void @@ -17,22 +17,42 @@ class ServerTimezoneSeeder extends Seeder $query->whereNull('server_timezone')->orWhere('server_timezone', ''); })->each(function ($server) use ($defaultTimezone) { DB::transaction(function () use ($server, $defaultTimezone) { - $server->settings->server_timezone = $defaultTimezone; - $server->settings->save(); - - $formComponent = new Form(); - $formComponent->server = $server; - $formComponent->updateServerTimezone($defaultTimezone); - - // Refresh the server settings to ensure we have the latest data - $server->settings->refresh(); - - // Double-check and set the timezone if it's still not set - if (!$server->settings->server_timezone) { - $server->settings->server_timezone = $defaultTimezone; - $server->settings->save(); - } + $this->updateServerTimezone($server, $defaultTimezone); }); }); } + + private function updateServerTimezone($server, $desired_timezone) + { + $commands = [ + "if command -v timedatectl > /dev/null 2>&1 && pidof systemd > /dev/null; then", + " timedatectl set-timezone " . escapeshellarg($desired_timezone), + "elif [ -f /etc/timezone ]; then", + " echo " . escapeshellarg($desired_timezone) . " > /etc/timezone", + " rm -f /etc/localtime", + " ln -sf /usr/share/zoneinfo/" . escapeshellarg($desired_timezone) . " /etc/localtime", + "elif [ -f /etc/localtime ]; then", + " rm -f /etc/localtime", + " ln -sf /usr/share/zoneinfo/" . escapeshellarg($desired_timezone) . " /etc/localtime", + "fi", + "if command -v dpkg-reconfigure > /dev/null 2>&1; then", + " dpkg-reconfigure -f noninteractive tzdata", + "elif command -v tzdata-update > /dev/null 2>&1; then", + " tzdata-update", + "elif [ -f /etc/sysconfig/clock ]; then", + " sed -i 's/^ZONE=.*/ZONE=\"" . $desired_timezone . "\"/' /etc/sysconfig/clock", + " source /etc/sysconfig/clock", + "fi", + "if command -v systemctl > /dev/null 2>&1 && pidof systemd > /dev/null; then", + " systemctl try-restart systemd-timesyncd.service || true", + "elif command -v service > /dev/null 2>&1; then", + " service ntpd restart || service ntp restart || true", + "fi" + ]; + + instant_remote_process($commands, $server); + + $server->settings->server_timezone = $desired_timezone; + $server->settings->save(); + } } From f366854671ccd1b9cdd466b9f7ec025abc27d79f Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 17:53:45 +0200 Subject: [PATCH 32/42] formatting --- .../views/livewire/server/form.blade.php | 272 +++++++++--------- 1 file changed, 135 insertions(+), 137 deletions(-) diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index b26122e57..30c0f7fdf 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -3,67 +3,67 @@

General

@if ($server->id === 0) - - You could lose a lot of functionalities if you change the server details of the server where Coolify - is - running on.
Please think again. -
+ + You could lose a lot of functionalities if you change the server details of the server where Coolify + is + running on.
Please think again. +
@else - Save - @if ($server->isFunctional()) - - Validate & configure - - - - - Revalidate server - - - @endif - @endif -
- @if ($server->isFunctional()) - Server is reachable and validated. - @else - You can't use this server until it is validated. - @endif - @if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id !== 0) + Save + @if ($server->isFunctional()) Validate & configure - + - - Validate Server & Install Docker Engine + + Revalidate server - @if ($server->validation_logs) -

Previous Validation Logs

-
- {!! $server->validation_logs !!} -
@endif + @endif +
+ @if ($server->isFunctional()) + Server is reachable and validated. + @else + You can't use this server until it is validated. + @endif + @if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id !== 0) + + Validate & configure + + + + + Validate Server & Install Docker Engine + + + @if ($server->validation_logs) +

Previous Validation Logs

+
+ {!! $server->validation_logs !!} +
+ @endif @endif @if ((!$server->settings->is_reachable || !$server->settings->is_usable) && $server->id === 0) - - Validate Server - + + Validate Server + @endif @if ($server->isForceDisabled() && isCloud()) -
The system has disabled the server because you have exceeded the - number of servers for which you have paid.
+
The system has disabled the server because you have exceeded the + number of servers for which you have paid.
@endif
@if (!$server->settings->is_swarm_worker && !$server->settings->is_build_server) - + @endif
+ wire:model.debounce.300ms="server.settings.server_timezone">
@@ -114,106 +112,106 @@
@if ($server->isFunctional()) - @if (!$server->isLocalhost()) - -
-

Cloudflare Tunnels -

- -
- @if ($server->settings->is_cloudflare_tunnel) - - @else - - - - @endif - @if (!$server->isBuildServer()) -

Swarm (experimental)

-
Read the docs here. -
- @if ($server->settings->is_swarm_worker) - - @else - - @endif - - @if ($server->settings->is_swarm_manager) - - @else - - @endif - @endif - @endif + @if (!$server->isLocalhost()) + +
+

Cloudflare Tunnels +

+ +
+ @if ($server->settings->is_cloudflare_tunnel) + @else -
-

Cloudflare Tunnels -

- -
- @if ($server->settings->is_cloudflare_tunnel) - - @else - - - - @endif + + + + @endif + @if (!$server->isBuildServer()) +

Swarm (experimental)

+
Read the docs here. +
+ @if ($server->settings->is_swarm_worker) + + @else + + @endif + + @if ($server->settings->is_swarm_manager) + + @else + + @endif + @endif + @endif + @else +
+

Cloudflare Tunnels +

+ +
+ @if ($server->settings->is_cloudflare_tunnel) + + @else + + + + @endif @endif
@if ($server->isFunctional()) -

Settings

-
-
- @if ($server->settings->is_force_cleanup_enabled) -
- -
- @else - -
- -
- @endif +

Settings

+
+
+ @if ($server->settings->is_force_cleanup_enabled) +
+
-
- - + @else + +
+
+ @endif
-
-

Sentinel

- {{-- @if ($server->isSentinelEnabled()) --}} - {{-- Restart --}} - {{-- @endif --}} +
+ +
-
Metrics are disabled until a few bugs are fixed.
- {{--
+
+
+

Sentinel

+ {{-- @if ($server->isSentinelEnabled()) --}} + {{-- Restart --}} + {{-- @endif --}} +
+
Metrics are disabled until a few bugs are fixed.
+ {{--
@@ -229,4 +227,4 @@
--}} @endif -
\ No newline at end of file +
From 165275cb6805b2b53602649aacedb99ae3385893 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 18:01:55 +0200 Subject: [PATCH 33/42] formatting --- .../scheduled-task/executions.blade.php | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php index 1129b4b11..58b53688d 100644 --- a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php @@ -1,34 +1,32 @@
@forelse($executions as $execution) - @if (data_get($execution, 'id') == $selectedKey) -
- @if (data_get($execution, 'message')) -
-
{{ data_get($execution, 'message') }}
-
- @else -
No output was recorded for this execution.
- @endif -
+ @if (data_get($execution, 'id') == $selectedKey) +
+ @if (data_get($execution, 'message')) +
+
{{ data_get($execution, 'message') }}
+
+ @else +
No output was recorded for this execution.
@endif - - data_get($execution, 'id') == $selectedKey, - 'border-green-500' => data_get($execution, 'status') === 'success', - 'border-red-500' => data_get($execution, 'status') === 'failed', +
+ @endif + + data_get($execution, 'id') == $selectedKey, + 'border-green-500' => data_get($execution, 'status') === 'success', + 'border-red-500' => data_get($execution, 'status') === 'failed', ])> - @if (data_get($execution, 'status') === 'running') -
- -
- @endif -
Status: {{ data_get($execution, 'status') }}
-
Started At: - {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at', now())) }} -
-
+ @if (data_get($execution, 'status') === 'running') +
+ +
+ @endif +
Status: {{ data_get($execution, 'status') }}
+
Started At: + {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at', now())) }} +
+ @empty -
No executions found.
+
No executions found.
@endforelse -
\ No newline at end of file +
From 4af7b8f451a7c633ea625f26d83ab6c0e948bef5 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 18:02:14 +0200 Subject: [PATCH 34/42] made function private again and remove unused code --- app/Livewire/Server/Form.php | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/app/Livewire/Server/Form.php b/app/Livewire/Server/Form.php index 55b81fdde..08054bd78 100644 --- a/app/Livewire/Server/Form.php +++ b/app/Livewire/Server/Form.php @@ -79,11 +79,6 @@ class Form extends Component $this->timezones = collect(timezone_identifiers_list())->sort()->values()->toArray(); $this->wildcard_domain = $this->server->settings->wildcard_domain; $this->cleanup_after_percentage = $this->server->settings->cleanup_after_percentage; - - // if ($this->server->settings->server_timezone === '') { - // $defaultTimezone = config('app.timezone'); - // $this->updateServerTimezone($defaultTimezone); - // } } public function serverInstalled() @@ -235,7 +230,7 @@ class Form extends Component $this->updateServerTimezone($value); } - public function updateServerTimezone($desired_timezone) + private function updateServerTimezone($desired_timezone) { try { $commands = [ From 789adc77fdbe7b0aaea3e23d78eaa970a279f9f1 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 19:29:44 +0200 Subject: [PATCH 35/42] fix DB server --- app/Models/ScheduledDatabaseBackup.php | 26 ++++++++++++-------------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/app/Models/ScheduledDatabaseBackup.php b/app/Models/ScheduledDatabaseBackup.php index a512a3f5f..e702aea5a 100644 --- a/app/Models/ScheduledDatabaseBackup.php +++ b/app/Models/ScheduledDatabaseBackup.php @@ -34,22 +34,20 @@ class ScheduledDatabaseBackup extends BaseModel { return $this->hasMany(ScheduledDatabaseBackupExecution::class)->where('created_at', '>=', now()->subDays($days))->get(); } - public function server() { - $database = $this->database; - if (!$database) { - return null; + if ($this->database) { + if ($this->database->destination && $this->database->destination->server) { + $server = $this->database->destination->server; + ray('Server found:', $server); + ray('Server details:', [ + 'id' => $server->id, + 'name' => $server->name, + 'ip' => $server->ip + ]); + return $server; + } } - - if (method_exists($database, 'server')) { - return $database->server; - } - - if (method_exists($database, 'service') && $database->service) { - return $database->service->server; - } - return null; } -} \ No newline at end of file +} From 62ecc45f216777e9fc2355ffb947e9b42ab41d6f Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:06:36 +0200 Subject: [PATCH 36/42] Feat: recent backups UI --- .../Project/Database/BackupExecutions.php | 49 ++++++++++++++++++- .../database/backup-executions.blade.php | 4 +- 2 files changed, 49 insertions(+), 4 deletions(-) diff --git a/app/Livewire/Project/Database/BackupExecutions.php b/app/Livewire/Project/Database/BackupExecutions.php index de1bac36f..79c1fcffc 100644 --- a/app/Livewire/Project/Database/BackupExecutions.php +++ b/app/Livewire/Project/Database/BackupExecutions.php @@ -8,9 +8,8 @@ use Livewire\Component; class BackupExecutions extends Component { public ?ScheduledDatabaseBackup $backup = null; - + public $database; public $executions = []; - public $setDeletableBackup; public function getListeners() @@ -61,4 +60,50 @@ class BackupExecutions extends Component $this->executions = $this->backup->executions()->get()->sortBy('created_at'); } } + + public function mount(ScheduledDatabaseBackup $backup) + { + $this->backup = $backup; + $this->database = $backup->database; + $this->refreshBackupExecutions(); + } + + public function server() + { + if ($this->database) { + $server = null; + + if ($this->database instanceof \App\Models\ServiceDatabase) { + $server = $this->database->service->destination->server; + } elseif ($this->database->destination && $this->database->destination->server) { + $server = $this->database->destination->server; + } + if ($server) { + return $server; + } + } + return null; + } + + public function getServerTimezone() + { + $server = $this->server(); + if (!$server) { + return 'UTC'; + } + $serverTimezone = $server->settings->server_timezone; + return $serverTimezone; + } + + public function formatDateInServerTimezone($date) + { + $serverTimezone = $this->getServerTimezone(); + $dateObj = new \DateTime($date); + try { + $dateObj->setTimezone(new \DateTimeZone($serverTimezone)); + } catch (\Exception $e) { + $dateObj->setTimezone(new \DateTimeZone('UTC')); + } + return $dateObj->format('Y-m-d H:i:s T'); + } } diff --git a/resources/views/livewire/project/database/backup-executions.blade.php b/resources/views/livewire/project/database/backup-executions.blade.php index 644ac9fa4..483fecc34 100644 --- a/resources/views/livewire/project/database/backup-executions.blade.php +++ b/resources/views/livewire/project/database/backup-executions.blade.php @@ -19,7 +19,7 @@ @endif
Database: {{ data_get($execution, 'database_name', 'N/A') }}
Status: {{ data_get($execution, 'status') }}
-
Started At: {{ data_get($execution, 'created_at') }}
+
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at')) }}
@if (data_get($execution, 'message'))
Message: {{ data_get($execution, 'message') }}
@endif @@ -54,4 +54,4 @@ @endisset -
+
\ No newline at end of file From 7a001cea3bd7802ddc5bf810f0923a90c0acc244 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:07:10 +0200 Subject: [PATCH 37/42] formatting --- .../database/scheduled-backups.blade.php | 57 +++++++++---------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/resources/views/livewire/project/database/scheduled-backups.blade.php b/resources/views/livewire/project/database/scheduled-backups.blade.php index 66b28eb39..d1ab8a3c1 100644 --- a/resources/views/livewire/project/database/scheduled-backups.blade.php +++ b/resources/views/livewire/project/database/scheduled-backups.blade.php @@ -1,38 +1,37 @@
@forelse($database->scheduledBackups as $backup) - @if ($type == 'database') - -
-
Frequency: {{ $backup->frequency }}
-
Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}
-
Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}
-
-
- @else -
-
- data_get($backup, 'id') === data_get($selectedBackup, 'id'), - 'flex flex-col border-l-2 border-transparent', - ])> -
Frequency: {{ $backup->frequency }}
-
Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}
-
Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}
-
-
- @endif + @if ($type == 'database') + +
+
Frequency: {{ $backup->frequency }}
+
Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}
+
Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}
+
+
+ @else +
+
+ data_get($backup, 'id') === data_get($selectedBackup, 'id'), + 'flex flex-col border-l-2 border-transparent', + ])> +
Frequency: {{ $backup->frequency }}
+
Last backup: {{ data_get($backup->latest_log, 'status', 'No backup yet') }}
+
Number of backups to keep (locally): {{ $backup->number_of_backups_locally }}
+
+
+ @endif @empty -
No scheduled backups configured.
+
No scheduled backups configured.
@endforelse
@if ($type === 'service-database' && $selectedBackup) -
- -

Executions

- -
+
+ +

Executions

+ +
@endif
From 80b90b3a2cd9f790234d3a38c0793987ff37fa47 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:21:37 +0200 Subject: [PATCH 38/42] fix UI of cron jobs --- .../Shared/ScheduledTask/Executions.php | 20 +++---------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Executions.php b/app/Livewire/Project/Shared/ScheduledTask/Executions.php index 16bc7bc5b..332b400b8 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Executions.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Executions.php @@ -29,37 +29,25 @@ class Executions extends Component public function server() { - ray('Entering server() In UI'); - if (!$this->task) { - ray('No task found, returning null'); return null; } if ($this->task->application) { - ray('Returning server from application'); return $this->task->application->server; - } elseif ($this->task->database) { - ray('Returning server from database'); - return $this->task->database->server; } elseif ($this->task->service) { - ray('Returning server from service'); return $this->task->service->server; } - - ray('No server found, returning null'); return null; } - + public function getServerTimezone() { $server = $this->server(); if (!$server) { - ray('No server found, returning default timezone'); return 'UTC'; } - $serverTimezone = $server->settings->server_timezone ?? 'UTC'; - ray('Server Timezone:', $serverTimezone); + $serverTimezone = $server->settings->server_timezone; return $serverTimezone; } @@ -70,10 +58,8 @@ class Executions extends Component try { $dateObj->setTimezone(new \DateTimeZone($serverTimezone)); } catch (\Exception $e) { - ray('Invalid timezone:', $serverTimezone); - // Fallback to UTC $dateObj->setTimezone(new \DateTimeZone('UTC')); } return $dateObj->format('Y-m-d H:i:s T'); } -} \ No newline at end of file +} From 48734e53d07ad82c659d82973809391c0a7b3f15 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 21:22:06 +0200 Subject: [PATCH 39/42] formatting --- app/Jobs/ScheduledTaskJob.php | 18 +-- app/Models/ScheduledTask.php | 3 +- .../database/backup-executions.blade.php | 103 +++++++++--------- .../shared/scheduled-task/show.blade.php | 64 +++++------ 4 files changed, 95 insertions(+), 93 deletions(-) diff --git a/app/Jobs/ScheduledTaskJob.php b/app/Jobs/ScheduledTaskJob.php index 3daaa9e83..93d5fca70 100644 --- a/app/Jobs/ScheduledTaskJob.php +++ b/app/Jobs/ScheduledTaskJob.php @@ -55,10 +55,13 @@ class ScheduledTaskJob implements ShouldQueue private function getServerTimezone(): string { if ($this->resource instanceof Application) { - return $this->resource->destination->server->settings->server_timezone; + $timezone = $this->resource->destination->server->settings->server_timezone; + return $timezone; } elseif ($this->resource instanceof Service) { - return $this->resource->server->settings->server_timezone; + $timezone = $this->resource->server->settings->server_timezone; + return $timezone; } + return 'UTC'; } public function middleware(): array @@ -91,12 +94,12 @@ class ScheduledTaskJob implements ShouldQueue } elseif ($this->resource->type() == 'service') { $this->resource->applications()->get()->each(function ($application) { if (str(data_get($application, 'status'))->contains('running')) { - $this->containers[] = data_get($application, 'name').'-'.data_get($this->resource, 'uuid'); + $this->containers[] = data_get($application, 'name') . '-' . data_get($this->resource, 'uuid'); } }); $this->resource->databases()->get()->each(function ($database) { if (str(data_get($database, 'status'))->contains('running')) { - $this->containers[] = data_get($database, 'name').'-'.data_get($this->resource, 'uuid'); + $this->containers[] = data_get($database, 'name') . '-' . data_get($this->resource, 'uuid'); } }); } @@ -109,8 +112,8 @@ class ScheduledTaskJob implements ShouldQueue } foreach ($this->containers as $containerName) { - if (count($this->containers) == 1 || str_starts_with($containerName, $this->task->container.'-'.$this->resource->uuid)) { - $cmd = "sh -c '".str_replace("'", "'\''", $this->task->command)."'"; + if (count($this->containers) == 1 || str_starts_with($containerName, $this->task->container . '-' . $this->resource->uuid)) { + $cmd = "sh -c '" . str_replace("'", "'\''", $this->task->command) . "'"; $exec = "docker exec {$containerName} {$cmd}"; $this->task_output = instant_remote_process([$exec], $this->server, true); $this->task_log->update([ @@ -135,7 +138,6 @@ class ScheduledTaskJob implements ShouldQueue // send_internal_notification('ScheduledTaskJob failed with: ' . $e->getMessage()); throw $e; } finally { - } } -} \ No newline at end of file +} diff --git a/app/Models/ScheduledTask.php b/app/Models/ScheduledTask.php index c01e5e057..81ca6dba5 100644 --- a/app/Models/ScheduledTask.php +++ b/app/Models/ScheduledTask.php @@ -38,7 +38,8 @@ class ScheduledTask extends BaseModel $server = $this->application->server; ray('Returning server from application: '.$server); return $server; - } elseif ($this->database) { + } + elseif ($this->database) { ray('Returning server from database'); $server = $this->database->server; ray('Returning server from database: '.$server); diff --git a/resources/views/livewire/project/database/backup-executions.blade.php b/resources/views/livewire/project/database/backup-executions.blade.php index 483fecc34..c3fc01fb4 100644 --- a/resources/views/livewire/project/database/backup-executions.blade.php +++ b/resources/views/livewire/project/database/backup-executions.blade.php @@ -1,57 +1,56 @@
@isset($backup) -
-

Executions

- Cleanup Failed Backups -
-
- @forelse($executions as $execution) -
data_get($execution, 'status') === 'success', - 'border-red-500' => data_get($execution, 'status') === 'failed', - ])> - @if (data_get($execution, 'status') === 'running') -
- -
- @endif -
Database: {{ data_get($execution, 'database_name', 'N/A') }}
-
Status: {{ data_get($execution, 'status') }}
-
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at')) }}
- @if (data_get($execution, 'message')) -
Message: {{ data_get($execution, 'message') }}
- @endif -
Size: {{ data_get($execution, 'size') }} B / - {{ round((int) data_get($execution, 'size') / 1024, 2) }} - kB / {{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB -
-
Location: {{ data_get($execution, 'filename', 'N/A') }}
-
-
- @if (data_get($execution, 'status') === 'success') - Download - @endif - - - Delete - - This will delete this backup. It is not reversible.
Please think again. -
-
-
+
+

Executions

+ Cleanup Failed Backups +
+
+ @forelse($executions as $execution) +
data_get($execution, 'status') === 'success', + 'border-red-500' => data_get($execution, 'status') === 'failed', + ])> + @if (data_get($execution, 'status') === 'running') +
+ +
+ @endif +
Database: {{ data_get($execution, 'database_name', 'N/A') }}
+
Status: {{ data_get($execution, 'status') }}
+
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at')) }}
+ @if (data_get($execution, 'message')) +
Message: {{ data_get($execution, 'message') }}
+ @endif +
Size: {{ data_get($execution, 'size') }} B / + {{ round((int) data_get($execution, 'size') / 1024, 2) }} + kB / {{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB +
+
Location: {{ data_get($execution, 'filename', 'N/A') }}
+
+
+ @if (data_get($execution, 'status') === 'success') + Download + @endif + + + Delete + + This will delete this backup. It is not reversible.
Please think again. +
+
+
- @empty -
No executions found.
- @endforelse -
- + @empty +
No executions found.
+ @endforelse +
+ @endisset -
\ No newline at end of file +
diff --git a/resources/views/livewire/project/shared/scheduled-task/show.blade.php b/resources/views/livewire/project/shared/scheduled-task/show.blade.php index d448000ca..125a431a4 100644 --- a/resources/views/livewire/project/shared/scheduled-task/show.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/show.blade.php @@ -1,47 +1,47 @@
{{ data_get_str($resource, 'name')->limit(10) }} > Scheduled Tasks | Coolify - - @if ($type === 'application') + + @if ($type === 'application')

Scheduled Task

- @elseif ($type === 'service') + @elseif ($type === 'service') - @endif + @endif -
-
-
-

Scheduled Task

- - Save - - - You will delete scheduled task {{ $task->name }}. - + +
+
+

Scheduled Task

+ + Save + + + You will delete scheduled task {{ $task->name }}. + +
+
+ +
-
- -
-
-
- - - - @if ($type === 'application') +
+ + + + @if ($type === 'application') - @elseif ($type === 'service') + @elseif ($type === 'service') - @endif -
- + @endif +
+ -
-

Recent executions (click to check output)

- -
-
\ No newline at end of file +
+

Recent executions (click to check output)

+ +
+
From 9ab03e52a32c41ea4b428921fa685a67e2e56529 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 22:03:43 +0200 Subject: [PATCH 40/42] remove ray --- app/Models/ScheduledDatabaseBackup.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/Models/ScheduledDatabaseBackup.php b/app/Models/ScheduledDatabaseBackup.php index e702aea5a..2d0e200da 100644 --- a/app/Models/ScheduledDatabaseBackup.php +++ b/app/Models/ScheduledDatabaseBackup.php @@ -39,12 +39,6 @@ class ScheduledDatabaseBackup extends BaseModel if ($this->database) { if ($this->database->destination && $this->database->destination->server) { $server = $this->database->destination->server; - ray('Server found:', $server); - ray('Server details:', [ - 'id' => $server->id, - 'name' => $server->name, - 'ip' => $server->ip - ]); return $server; } } From a0689ca5fc6b7d7c5f75527d35b5a8a7a777dc31 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 16 Aug 2024 22:05:38 +0200 Subject: [PATCH 41/42] fix cron issues for UI and applications --- .../Shared/ScheduledTask/Executions.php | 8 +++-- app/Models/ScheduledTask.php | 35 +++++++++---------- 2 files changed, 22 insertions(+), 21 deletions(-) diff --git a/app/Livewire/Project/Shared/ScheduledTask/Executions.php b/app/Livewire/Project/Shared/ScheduledTask/Executions.php index 332b400b8..5bd6b4b9b 100644 --- a/app/Livewire/Project/Shared/ScheduledTask/Executions.php +++ b/app/Livewire/Project/Shared/ScheduledTask/Executions.php @@ -34,9 +34,13 @@ class Executions extends Component } if ($this->task->application) { - return $this->task->application->server; + if ($this->task->application->destination && $this->task->application->destination->server) { + return $this->task->application->destination->server; + } } elseif ($this->task->service) { - return $this->task->service->server; + if ($this->task->service->destination && $this->task->service->destination->server) { + return $this->task->service->destination->server; + } } return null; } diff --git a/app/Models/ScheduledTask.php b/app/Models/ScheduledTask.php index 81ca6dba5..4641c2a85 100644 --- a/app/Models/ScheduledTask.php +++ b/app/Models/ScheduledTask.php @@ -4,6 +4,8 @@ namespace App\Models; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Database\Eloquent\Relations\HasOne; +use App\Models\Service; +use App\Models\Application; class ScheduledTask extends BaseModel { @@ -31,27 +33,22 @@ class ScheduledTask extends BaseModel public function server() { - ray('Entering server() method in ScheduledTask model'); - if ($this->application) { - ray('Returning server from application'); - $server = $this->application->server; - ray('Returning server from application: '.$server); - return $server; - } - elseif ($this->database) { - ray('Returning server from database'); - $server = $this->database->server; - ray('Returning server from database: '.$server); - return $server; + if ($this->application->destination && $this->application->destination->server) { + $server = $this->application->destination->server; + return $server; + } } elseif ($this->service) { - ray('Returning server from service'); - $server = $this->service->server; - ray('Returning server from service: '.$server); - return $server; + if ($this->service->destination && $this->service->destination->server) { + $server = $this->service->destination->server; + return $server; + } + } elseif ($this->database) { + if ($this->database->destination && $this->database->destination->server) { + $server = $this->database->destination->server; + return $server; + } } - - ray('No server found, returning null'); return null; } -} \ No newline at end of file +} From 7d4261b71a850af4b8fe80f48d5ef739cd55a1b7 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Mon, 19 Aug 2024 00:14:09 +0200 Subject: [PATCH 42/42] new design for execution log --- .../database/backup-executions.blade.php | 56 +++++++++++-------- .../scheduled-task/executions.blade.php | 26 +++++---- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/resources/views/livewire/project/database/backup-executions.blade.php b/resources/views/livewire/project/database/backup-executions.blade.php index c3fc01fb4..b1cc7fa66 100644 --- a/resources/views/livewire/project/database/backup-executions.blade.php +++ b/resources/views/livewire/project/database/backup-executions.blade.php @@ -4,33 +4,45 @@

Executions

Cleanup Failed Backups -
+
@forelse($executions as $execution) -
data_get($execution, 'status') === 'success', - 'border-red-500' => data_get($execution, 'status') === 'failed', +
data_get($execution, 'status') === 'success', + 'border-red-500' => data_get($execution, 'status') === 'failed', + 'border-yellow-500' => data_get($execution, 'status') === 'running', ])> @if (data_get($execution, 'status') === 'running')
@endif -
Database: {{ data_get($execution, 'database_name', 'N/A') }}
-
Status: {{ data_get($execution, 'status') }}
-
Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at')) }}
- @if (data_get($execution, 'message')) -
Message: {{ data_get($execution, 'message') }}
- @endif -
Size: {{ data_get($execution, 'size') }} B / - {{ round((int) data_get($execution, 'size') / 1024, 2) }} - kB / {{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB +
Status: {{ data_get($execution, 'status') }}
+
+ Started At: {{ $this->formatDateInServerTimezone(data_get($execution, 'created_at')) }}
-
Location: {{ data_get($execution, 'filename', 'N/A') }}
-
-
+
+ Database: {{ data_get($execution, 'database_name', 'N/A') }} +
+
+ Size: {{ data_get($execution, 'size') }} B / + {{ round((int) data_get($execution, 'size') / 1024, 2) }} kB / + {{ round((int) data_get($execution, 'size') / 1024 / 1024, 3) }} MB +
+
+ Location: {{ data_get($execution, 'filename', 'N/A') }} +
+ @if (data_get($execution, 'message')) +
+
{{ data_get($execution, 'message') }}
+
+ @endif +
@if (data_get($execution, 'status') === 'success') - Download @endif @@ -40,10 +52,9 @@ This will delete this backup. It is not reversible.
Please think again.
- - +
@empty -
No executions found.
+
No executions found.
@endforelse
@endisset - -
+
\ No newline at end of file diff --git a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php index 58b53688d..a52713522 100644 --- a/resources/views/livewire/project/shared/scheduled-task/executions.blade.php +++ b/resources/views/livewire/project/shared/scheduled-task/executions.blade.php @@ -1,32 +1,36 @@ -