From 5030c14dc24bf4c4b18eed11f8e7416327efc5f6 Mon Sep 17 00:00:00 2001 From: RayBB Date: Sun, 3 Mar 2024 23:42:33 +0100 Subject: [PATCH 01/11] add changedetection.io template --- templates/compose/changedetection.yaml | 34 ++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 templates/compose/changedetection.yaml diff --git a/templates/compose/changedetection.yaml b/templates/compose/changedetection.yaml new file mode 100644 index 000000000..91704e7f1 --- /dev/null +++ b/templates/compose/changedetection.yaml @@ -0,0 +1,34 @@ +# documentation: https://github.com/dgtlmoon/changedetection.io/ +# slogan: Website change detection monitor and notifications +# tags: web, alert, monitor + +services: + changedetection: + image: ghcr.io/dgtlmoon/changedetection.io + container_name: changedetection + hostname: changedetection + volumes: + - changedetection-data:/datastore + environment: + - SERVICE_FQDN_CHANGEDETECTION + - PUID=1000 + - PGID=1000 + - BASE_URL=$SERVICE_FQDN_CHANGEDETECTION + - PLAYWRIGHT_DRIVER_URL=ws://playwright-chrome:3000/?stealth=1&--disable-web-security=true + # Hides the `Referer` header so that monitored websites can't see the changedetection.io hostname. + - HIDE_REFERER=true + depends_on: + playwright-chrome: + condition: service_started + playwright-chrome: + hostname: playwright-chrome + image: dgtlmoon/sockpuppetbrowser:latest + # cap_add: + # - SYS_ADMIN + # SYS_ADMIN might be too much, but it can be needed on your platform https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#running-puppeteer-on-gitlabci + restart: unless-stopped + environment: + - SCREEN_WIDTH=1920 + - SCREEN_HEIGHT=1024 + - SCREEN_DEPTH=16 + - MAX_CONCURRENT_CHROME_PROCESSES=10 From f7e1ce86566739e0e92683dbdb5a6b5b5ba5d0d6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 08:49:53 +0100 Subject: [PATCH 02/11] fix: env value generation --- app/Exceptions/Handler.php | 3 +++ bootstrap/helpers/shared.php | 4 ++-- config/sentry.php | 2 +- config/version.php | 2 +- versions.json | 2 +- 5 files changed, 8 insertions(+), 5 deletions(-) diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index f010c33b6..2584df48b 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -77,6 +77,9 @@ function (Scope $scope) { ); } ); + if (str($e->getMessage())->contains('No space left on device')) { + return; + } ray('reporting to sentry'); Integration::captureUnhandledException($e); }); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 86a874985..0911aa118 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1405,7 +1405,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal ]); } } else { - $generatedValue = generateEnvValue($command, $service); + $generatedValue = generateEnvValue($command); if (!$foundEnv) { EnvironmentVariable::create([ 'key' => $key, @@ -1581,7 +1581,7 @@ function parseEnvVariable(Str|string $value) 'port' => $port, ]; } -function generateEnvValue(string $command, Service $service) +function generateEnvValue(string $command, ?Service $service = null) { switch ($command) { case 'PASSWORD': diff --git a/config/sentry.php b/config/sentry.php index 438c45246..13331bc77 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ // The release version of your application // Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD')) - 'release' => '4.0.0-beta.232', + 'release' => '4.0.0-beta.233', // When left empty or `null` the Laravel environment will be used 'environment' => config('app.env'), diff --git a/config/version.php b/config/version.php index 2ff41e455..7aab683f5 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Mon, 4 Mar 2024 08:51:24 +0100 Subject: [PATCH 03/11] fix: sentry error --- app/Jobs/DatabaseBackupJob.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 8a854128a..71de3e352 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -51,6 +51,9 @@ public function __construct($backup) { $this->backup = $backup; $this->team = Team::find($backup->team_id); + if (is_null($this->team)) { + return; + } if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') { $this->database = data_get($this->backup, 'database'); $this->server = $this->database->service->server; From 0aa85a370125c3bc29cd17ccb0661f4edf963358 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 08:57:18 +0100 Subject: [PATCH 04/11] fix: service status updated --- app/Livewire/Project/Service/Configuration.php | 1 + app/Livewire/Project/Service/Navbar.php | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/Livewire/Project/Service/Configuration.php b/app/Livewire/Project/Service/Configuration.php index 33aac21d0..69d158c04 100644 --- a/app/Livewire/Project/Service/Configuration.php +++ b/app/Livewire/Project/Service/Configuration.php @@ -18,6 +18,7 @@ public function getListeners() $userId = auth()->user()->id; return [ "echo-private:user.{$userId},ServiceStatusChanged" => 'check_status', + "check_status" ]; } public function render() diff --git a/app/Livewire/Project/Service/Navbar.php b/app/Livewire/Project/Service/Navbar.php index 70c304de0..30e96b838 100644 --- a/app/Livewire/Project/Service/Navbar.php +++ b/app/Livewire/Project/Service/Navbar.php @@ -6,7 +6,6 @@ use App\Actions\Service\StartService; use App\Actions\Service\StopService; use App\Events\ServiceStatusChanged; -use App\Jobs\ContainerStatusJob; use App\Models\Service; use Livewire\Component; use Spatie\Activitylog\Models\Activity; @@ -27,6 +26,10 @@ public function serviceStatusChanged() { $this->dispatch('refresh')->self(); } + public function check_status() { + $this->dispatch('check_status'); + $this->dispatch('success', 'Service status updated.'); + } public function render() { return view('livewire.project.service.navbar'); From 62278126e428bc851e989784f5ba7e68cc8af0b0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 09:12:23 +0100 Subject: [PATCH 05/11] fixes --- app/Livewire/Server/Proxy.php | 2 +- bootstrap/helpers/shared.php | 1 - resources/views/livewire/project/application/general.blade.php | 2 ++ resources/views/livewire/project/shared/get-logs.blade.php | 2 +- 4 files changed, 4 insertions(+), 3 deletions(-) diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php index 5825cf3fb..98dd75861 100644 --- a/app/Livewire/Server/Proxy.php +++ b/app/Livewire/Server/Proxy.php @@ -26,7 +26,7 @@ public function mount() public function proxyStatusUpdated() { - $this->server->refresh(); + $this->dispatch('refresh')->self(); } public function change_proxy() diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 0911aa118..47dd8b284 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1249,7 +1249,6 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal // Collect/create/update networks if ($serviceNetworks->count() > 0) { foreach ($serviceNetworks as $networkName => $networkDetails) { - ray($networkDetails); $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) { return $value == $networkName || $key == $networkName; }); diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index aa104267b..26fdd935b 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -45,9 +45,11 @@ @endif @if ($application->build_pack === 'dockercompose') +
+
@if (count($parsedServices) > 0 && !$application->settings->is_raw_compose_deployment_enabled) @foreach (data_get($parsedServices, 'services') as $serviceName => $service) @if (!isDatabaseImage(data_get($service, 'image'))) diff --git a/resources/views/livewire/project/shared/get-logs.blade.php b/resources/views/livewire/project/shared/get-logs.blade.php index 3728ca9b6..c72f2fd2a 100644 --- a/resources/views/livewire/project/shared/get-logs.blade.php +++ b/resources/views/livewire/project/shared/get-logs.blade.php @@ -1,7 +1,7 @@
- @if ($resource->type() === 'application') + @if ($resource?->type() === 'application')

{{ $container }}

@else

{{ str($container)->beforeLast('-')->headline() }}

From 0dd591a5ff564462a75682da4762e066b016fd00 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 10:13:40 +0100 Subject: [PATCH 06/11] fix: raw compose make dirs fix: raw compose add coolify labels --- app/Jobs/ApplicationDeploymentJob.php | 32 +++++++--- app/Livewire/Project/Application/General.php | 6 +- app/Models/Application.php | 63 +++++++++++++++++++ app/Models/LocalFileVolume.php | 1 - .../components/applications/links.blade.php | 6 +- 5 files changed, 97 insertions(+), 11 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 8ecaacc98..0dedfd596 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -374,6 +374,7 @@ private function deploy_docker_compose_buildpack() $this->cleanup_git(); $this->application->loadComposeFile(isInit: false); if ($this->application->settings->is_raw_compose_deployment_enabled) { + $this->application->parseRawCompose(); $yaml = $composeFile = $this->application->docker_compose_raw; } else { $composeFile = $this->application->parseCompose(pull_request_id: $this->pull_request_id); @@ -413,16 +414,33 @@ private function deploy_docker_compose_buildpack() ]); } $this->write_deployment_configurations(); + // Start compose file - if ($this->docker_compose_custom_start_command) { - $this->execute_remote_command( - [executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), "hidden" => true], - ); + if ($this->application->settings->is_raw_compose_deployment_enabled) { + if ($this->docker_compose_custom_start_command) { + $this->execute_remote_command( + ["cd {$this->basedir} && {$this->docker_compose_custom_start_command}", "hidden" => true], + ); + } else { + $server_workdir = $this->application->workdir(); + ray("SOURCE_COMMIT={$this->commit} docker compose --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d"); + $this->execute_remote_command( + ["SOURCE_COMMIT={$this->commit} docker compose --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d", "hidden" => true], + ); + } } else { - $this->execute_remote_command( - [executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"), "hidden" => true], - ); + if ($this->docker_compose_custom_start_command) { + $this->execute_remote_command( + [executeInDocker($this->deployment_uuid, "cd {$this->basedir} && {$this->docker_compose_custom_start_command}"), "hidden" => true], + ); + } else { + $this->execute_remote_command( + [executeInDocker($this->deployment_uuid, "SOURCE_COMMIT={$this->commit} docker compose --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"), "hidden" => true], + ); + } } + + $this->application_deployment_queue->addLogEntry("New container started."); } private function deploy_dockerfile_buildpack() diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index b3c565fdd..3279ff2d5 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -263,7 +263,11 @@ public function submit($showToaster = true) } if ($this->application->build_pack === 'dockercompose') { $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains); - $this->parsedServices = $this->application->parseCompose(); + if ($this->application->settings->is_raw_compose_deployment_enabled) { + $this->application->parseRawCompose(); + } else { + $this->parsedServices = $this->application->parseCompose(); + } } $this->application->custom_labels = base64_encode($this->customLabels); $this->application->save(); diff --git a/app/Models/Application.php b/app/Models/Application.php index 4cb941215..f6df1ca88 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -9,6 +9,7 @@ use Spatie\Activitylog\Models\Activity; use Illuminate\Support\Str; use RuntimeException; +use Symfony\Component\Yaml\Yaml; use Visus\Cuid2\Cuid2; class Application extends BaseModel @@ -476,6 +477,10 @@ public function isHealthcheckDisabled(): bool } return false; } + public function workdir() + { + return application_configuration_dir() . "/{$this->uuid}"; + } public function isLogDrainEnabled() { return data_get($this, 'settings.is_log_drain_enabled', false); @@ -710,6 +715,64 @@ function generateGitImportCommands(string $deployment_uuid, int $pull_request_id ]; } } + function parseRawCompose() + { + try { + $yaml = Yaml::parse($this->docker_compose_raw); + } catch (\Exception $e) { + throw new \Exception($e->getMessage()); + } + $services = data_get($yaml, 'services'); + $commands = collect([]); + $services = collect($services)->map(function ($service) use ($commands) { + $serviceVolumes = collect(data_get($service, 'volumes', [])); + if ($serviceVolumes->count() > 0) { + foreach ($serviceVolumes as $volume) { + $workdir = $this->workdir(); + $type = null; + $source = null; + if (is_string($volume)) { + $source = Str::of($volume)->before(':'); + if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) { + $type = Str::of('bind'); + } + } else if (is_array($volume)) { + $type = data_get_str($volume, 'type'); + $source = data_get_str($volume, 'source'); + } + if ($type->value() === 'bind') { + if ($source->value() === "/var/run/docker.sock") { + continue; + } + if ($source->value() === '/tmp' || $source->value() === '/tmp/') { + continue; + } + if ($source->startsWith('.')) { + $source = $source->after('.'); + $source = $workdir . $source; + } + $commands->push("mkdir -p $source > /dev/null 2>&1 || true"); + } + } + } + $labels = collect(data_get($service, 'labels', [])); + if (!$labels->contains('coolify.managed')) { + $labels->push('coolify.managed=true'); + } + if (!$labels->contains('coolify.applicationId')) { + $labels->push('coolify.applicationId=' . $this->id); + } + if (!$labels->contains('coolify.type')) { + $labels->push('coolify.type=application'); + } + data_set($service, 'labels', $labels->toArray()); + return $service; + }); + data_set($yaml, 'services', $services->toArray()); + $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); + + instant_remote_process($commands, $this->destination->server, false); + } function parseCompose(int $pull_request_id = 0) { if ($this->docker_compose_raw) { diff --git a/app/Models/LocalFileVolume.php b/app/Models/LocalFileVolume.php index 3e032db0f..a0447b581 100644 --- a/app/Models/LocalFileVolume.php +++ b/app/Models/LocalFileVolume.php @@ -3,7 +3,6 @@ namespace App\Models; use Illuminate\Database\Eloquent\Factories\HasFactory; -use Illuminate\Support\Str; class LocalFileVolume extends BaseModel { diff --git a/resources/views/components/applications/links.blade.php b/resources/views/components/applications/links.blade.php index 92acb01a2..7f3bed2da 100644 --- a/resources/views/components/applications/links.blade.php +++ b/resources/views/components/applications/links.blade.php @@ -1,8 +1,10 @@
- @if (data_get($application, 'fqdn') || + @if ( + (data_get($application, 'fqdn') || collect(json_decode($this->application->docker_compose_domains))->count() > 0 || data_get($application, 'previews', collect([]))->count() > 0 || - data_get($application, 'ports_mappings_array')) + data_get($application, 'ports_mappings_array')) && + data_get($application, 'settings.is_raw_compose_deployment_enabled') !== true) From cee6b540334acb8b6121feffbf18ee029de8c071 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 10:42:54 +0100 Subject: [PATCH 07/11] Add proxy start functionality when selecting a proxy type --- app/Actions/Proxy/StartProxy.php | 3 +++ app/Livewire/Server/Proxy.php | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/app/Actions/Proxy/StartProxy.php b/app/Actions/Proxy/StartProxy.php index 99206606d..e106c1801 100644 --- a/app/Actions/Proxy/StartProxy.php +++ b/app/Actions/Proxy/StartProxy.php @@ -15,6 +15,9 @@ public function handle(Server $server, bool $async = true): string|Activity { try { $proxyType = $server->proxyType(); + if ($proxyType === 'NONE') { + return 'OK'; + } $commands = collect([]); $proxy_path = get_proxy_path(); $configuration = CheckConfiguration::run($server); diff --git a/app/Livewire/Server/Proxy.php b/app/Livewire/Server/Proxy.php index 98dd75861..1e23605ff 100644 --- a/app/Livewire/Server/Proxy.php +++ b/app/Livewire/Server/Proxy.php @@ -4,6 +4,7 @@ use App\Actions\Proxy\CheckConfiguration; use App\Actions\Proxy\SaveConfiguration; +use App\Actions\Proxy\StartProxy; use App\Models\Server; use Livewire\Component; use Illuminate\Support\Str; @@ -41,6 +42,9 @@ public function select_proxy($proxy_type) $this->server->proxy->set('type', $proxy_type); $this->server->save(); $this->selectedProxy = $this->server->proxy->type; + if ($this->selectedProxy !== 'NONE') { + StartProxy::run($this->server, false); + } $this->dispatch('proxyStatusUpdated'); } From 8385bbb0a07a2b38c54563cf477ed091771e32a5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 10:46:13 +0100 Subject: [PATCH 08/11] feat: gzip enabled & stipprefix setting refactor: code --- app/Actions/Database/StartMariadb.php | 2 +- app/Actions/Database/StartMongodb.php | 2 +- app/Actions/Database/StartMysql.php | 2 +- app/Actions/Database/StartPostgresql.php | 2 +- app/Actions/Database/StartRedis.php | 2 +- app/Console/Kernel.php | 2 +- app/Jobs/ApplicationDeploymentJob.php | 2 +- app/Jobs/DatabaseBackupJob.php | 2 +- app/Livewire/Project/Application/Advanced.php | 18 ++++++++-- .../Project/Database/Mariadb/General.php | 8 ++--- .../Project/Database/Mongodb/General.php | 8 ++--- .../Project/Database/Mysql/General.php | 8 ++--- .../Project/Database/Postgresql/General.php | 8 ++--- .../Project/Database/Redis/General.php | 8 ++--- app/Livewire/Project/Service/Database.php | 2 +- .../Service/ServiceApplicationView.php | 3 +- app/Livewire/Server/LogDrains.php | 2 +- app/Models/Application.php | 14 +++++++- app/Models/Server.php | 2 +- app/Models/ServiceApplication.php | 8 +++-- app/Models/ServiceDatabase.php | 4 +-- app/Models/StandaloneMariadb.php | 4 +-- app/Models/StandaloneMongodb.php | 4 +-- app/Models/StandaloneMysql.php | 4 +-- app/Models/StandalonePostgresql.php | 4 +-- app/Models/StandaloneRedis.php | 4 +-- bootstrap/helpers/docker.php | 23 ++++++++---- bootstrap/helpers/shared.php | 13 +++++-- ..._gzip_enabled_and_stripprefix_settings.php | 36 +++++++++++++++++++ .../project/application/advanced.blade.php | 5 +++ .../service-application-view.blade.php | 4 ++- .../livewire/server/log-drains.blade.php | 6 ++-- 32 files changed, 154 insertions(+), 62 deletions(-) create mode 100644 database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php diff --git a/app/Actions/Database/StartMariadb.php b/app/Actions/Database/StartMariadb.php index 8dca584f2..3274566a1 100644 --- a/app/Actions/Database/StartMariadb.php +++ b/app/Actions/Database/StartMariadb.php @@ -71,7 +71,7 @@ public function handle(StandaloneMariadb $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { + if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php index ef04a9be8..75bfe3ed3 100644 --- a/app/Actions/Database/StartMongodb.php +++ b/app/Actions/Database/StartMongodb.php @@ -78,7 +78,7 @@ public function handle(StandaloneMongodb $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { + if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Actions/Database/StartMysql.php b/app/Actions/Database/StartMysql.php index 3b47483a3..4a8edc1e2 100644 --- a/app/Actions/Database/StartMysql.php +++ b/app/Actions/Database/StartMysql.php @@ -71,7 +71,7 @@ public function handle(StandaloneMysql $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { + if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php index 844f81c31..ea5de10da 100644 --- a/app/Actions/Database/StartPostgresql.php +++ b/app/Actions/Database/StartPostgresql.php @@ -77,7 +77,7 @@ public function handle(StandalonePostgresql $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { + if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { ray('Log Drain Enabled'); $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index e1a8eef41..692c14c1c 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -81,7 +81,7 @@ public function handle(StandaloneRedis $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { + if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index e92c602cf..4599dd5a4 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -77,7 +77,7 @@ private function check_resources($schedule) // ray('dispatching container status job in ' . $randomSeconds . ' seconds'); // dispatch($job); // })->name('container-status-' . $server->id)->everyMinute()->onOneServer(); - if ($server->isLogDrainEnabled()) { + if ($server->is_log_drain_enabled()) { $schedule->job(new CheckLogDrainContainerJob($server))->everyMinute()->onOneServer(); // $schedule // ->call(function () use ($server) { diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 0dedfd596..29709d675 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1185,7 +1185,7 @@ private function generate_compose_file() } else { $docker_compose['services'][$this->container_name]['labels'] = $labels; } - if ($this->server->isLogDrainEnabled() && $this->application->isLogDrainEnabled()) { + if ($this->server->is_log_drain_enabled() && $this->application->is_log_drain_enabled()) { $docker_compose['services'][$this->container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Jobs/DatabaseBackupJob.php b/app/Jobs/DatabaseBackupJob.php index 71de3e352..aa4b2fa7f 100644 --- a/app/Jobs/DatabaseBackupJob.php +++ b/app/Jobs/DatabaseBackupJob.php @@ -319,7 +319,7 @@ public function handle(): void private function backup_standalone_mongodb(string $databaseWithCollections): void { try { - $url = $this->database->getDbUrl(useInternal: true); + $url = $this->database->get_db_url(useInternal: true); if ($databaseWithCollections === 'all') { $commands[] = "mkdir -p " . $this->backup_dir; $commands[] = "docker exec $this->container_name mongodump --authenticationDatabase=admin --uri=$url --gzip --archive > $this->backup_location"; diff --git a/app/Livewire/Project/Application/Advanced.php b/app/Livewire/Project/Application/Advanced.php index 08b4f9523..442f5488a 100644 --- a/app/Livewire/Project/Application/Advanced.php +++ b/app/Livewire/Project/Application/Advanced.php @@ -9,6 +9,8 @@ class Advanced extends Component { public Application $application; public bool $is_force_https_enabled; + public bool $is_gzip_enabled; + public bool $is_stripprefix_enabled; protected $rules = [ 'application.settings.is_git_submodules_enabled' => 'boolean|required', 'application.settings.is_git_lfs_enabled' => 'boolean|required', @@ -19,6 +21,8 @@ class Advanced extends Component 'application.settings.is_gpu_enabled' => 'boolean|required', 'application.settings.is_build_server_enabled' => 'boolean|required', 'application.settings.is_consistent_container_name_enabled' => 'boolean|required', + 'application.settings.is_gzip_enabled' => 'boolean|required', + 'application.settings.is_stripprefix_enabled' => 'boolean|required', 'application.settings.gpu_driver' => 'string|required', 'application.settings.gpu_count' => 'string|required', 'application.settings.gpu_device_ids' => 'string|required', @@ -26,11 +30,13 @@ class Advanced extends Component ]; public function mount() { $this->is_force_https_enabled = $this->application->settings->is_force_https_enabled; + $this->is_gzip_enabled = $this->application->settings->is_gzip_enabled; + $this->is_stripprefix_enabled = $this->application->settings->is_stripprefix_enabled; } public function instantSave() { - if ($this->application->isLogDrainEnabled()) { - if (!$this->application->destination->server->isLogDrainEnabled()) { + if ($this->application->is_log_drain_enabled()) { + if (!$this->application->destination->server->is_log_drain_enabled()) { $this->application->settings->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on this server.'); return; @@ -40,6 +46,14 @@ public function instantSave() $this->application->settings->is_force_https_enabled = $this->is_force_https_enabled; $this->dispatch('resetDefaultLabels', false); } + if ($this->application->settings->is_gzip_enabled !== $this->is_gzip_enabled) { + $this->application->settings->is_gzip_enabled = $this->is_gzip_enabled; + $this->dispatch('resetDefaultLabels', false); + } + if ($this->application->settings->is_stripprefix_enabled !== $this->is_stripprefix_enabled) { + $this->application->settings->is_stripprefix_enabled = $this->is_stripprefix_enabled; + $this->dispatch('resetDefaultLabels', false); + } $this->application->settings->save(); $this->dispatch('success', 'Settings saved.'); } diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php index 9b15c6c3c..9e0a0c5fc 100644 --- a/app/Livewire/Project/Database/Mariadb/General.php +++ b/app/Livewire/Project/Database/Mariadb/General.php @@ -46,14 +46,14 @@ class General extends Component public function mount() { - $this->db_url = $this->database->getDbUrl(true); + $this->db_url = $this->database->get_db_url(true); if ($this->database->is_public) { - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); } } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->isLogDrainEnabled()) { + if (!$this->database->destination->server->is_log_drain_enabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; @@ -93,7 +93,7 @@ public function instantSave() return; } StartDatabaseProxy::run($this->database); - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php index cd3ea0630..5c9f9cb47 100644 --- a/app/Livewire/Project/Database/Mongodb/General.php +++ b/app/Livewire/Project/Database/Mongodb/General.php @@ -44,15 +44,15 @@ class General extends Component public function mount() { - $this->db_url = $this->database->getDbUrl(true); + $this->db_url = $this->database->get_db_url(true); if ($this->database->is_public) { - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); } } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->isLogDrainEnabled()) { + if (!$this->database->destination->server->is_log_drain_enabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; @@ -95,7 +95,7 @@ public function instantSave() return; } StartDatabaseProxy::run($this->database); - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php index 2470a934b..f67641b31 100644 --- a/app/Livewire/Project/Database/Mysql/General.php +++ b/app/Livewire/Project/Database/Mysql/General.php @@ -46,15 +46,15 @@ class General extends Component public function mount() { - $this->db_url = $this->database->getDbUrl(true); + $this->db_url = $this->database->get_db_url(true); if ($this->database->is_public) { - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); } } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->isLogDrainEnabled()) { + if (!$this->database->destination->server->is_log_drain_enabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; @@ -94,7 +94,7 @@ public function instantSave() return; } StartDatabaseProxy::run($this->database); - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index 43f559140..102557351 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -53,14 +53,14 @@ class General extends Component ]; public function mount() { - $this->db_url = $this->database->getDbUrl(true); + $this->db_url = $this->database->get_db_url(true); if ($this->database->is_public) { - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); } } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->isLogDrainEnabled()) { + if (!$this->database->destination->server->is_log_drain_enabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; @@ -87,7 +87,7 @@ public function instantSave() return; } StartDatabaseProxy::run($this->database); - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index 07c161de5..ee02239af 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -39,14 +39,14 @@ class General extends Component ]; public function mount() { - $this->db_url = $this->database->getDbUrl(true); + $this->db_url = $this->database->get_db_url(true); if ($this->database->is_public) { - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); } } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->isLogDrainEnabled()) { + if (!$this->database->destination->server->is_log_drain_enabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; @@ -86,7 +86,7 @@ public function instantSave() return; } StartDatabaseProxy::run($this->database); - $this->db_url_public = $this->database->getDbUrl(); + $this->db_url_public = $this->database->get_db_url(); $this->dispatch('success', 'Database is now publicly accessible.'); } else { StopDatabaseProxy::run($this->database); diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index 8dec97852..c86c54da2 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -36,7 +36,7 @@ public function mount() } public function instantSaveAdvanced() { - if (!$this->database->service->destination->server->isLogDrainEnabled()) { + if (!$this->database->service->destination->server->is_log_drain_enabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Service/ServiceApplicationView.php b/app/Livewire/Project/Service/ServiceApplicationView.php index 2bae41a80..9a4738c9f 100644 --- a/app/Livewire/Project/Service/ServiceApplicationView.php +++ b/app/Livewire/Project/Service/ServiceApplicationView.php @@ -18,6 +18,7 @@ class ServiceApplicationView extends Component 'application.required_fqdn' => 'required|boolean', 'application.is_log_drain_enabled' => 'nullable|boolean', 'application.is_gzip_enabled' => 'nullable|boolean', + 'application.is_stripprefix_enabled' => 'nullable|boolean', ]; public function render() { @@ -29,7 +30,7 @@ public function instantSave() } public function instantSaveAdvanced() { - if (!$this->application->service->destination->server->isLogDrainEnabled()) { + if (!$this->application->service->destination->server->is_log_drain_enabled()) { $this->application->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index 4eca682d4..605aa25b5 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -54,7 +54,7 @@ public function configureLogDrain() { try { InstallLogDrain::run($this->server); - if (!$this->server->isLogDrainEnabled()) { + if (!$this->server->is_log_drain_enabled()) { $this->dispatch('serverRefresh'); $this->dispatch('success', 'Log drain service stopped.'); return; diff --git a/app/Models/Application.php b/app/Models/Application.php index f6df1ca88..24a61eca9 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -80,6 +80,18 @@ public function is_github_based(): bool } return false; } + public function is_force_https_enabled() + { + return data_get($this, 'settings.is_force_https_enabled', false); + } + public function is_stripprefix_enabled() + { + return data_get($this, 'settings.is_stripprefix_enabled', true); + } + public function is_gzip_enabled() + { + return data_get($this, 'settings.is_gzip_enabled', true); + } public function link() { if (data_get($this, 'environment.project.uuid')) { @@ -481,7 +493,7 @@ public function workdir() { return application_configuration_dir() . "/{$this->uuid}"; } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'settings.is_log_drain_enabled', false); } diff --git a/app/Models/Server.php b/app/Models/Server.php index 4028109e2..5293bdd99 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -405,7 +405,7 @@ public function isFunctional() { return $this->settings->is_reachable && $this->settings->is_usable && !$this->settings->force_disabled; } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return $this->settings->is_logdrain_newrelic_enabled || $this->settings->is_logdrain_highlight_enabled || $this->settings->is_logdrain_axiom_enabled || $this->settings->is_logdrain_custom_enabled; } diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index 314a01ba3..8a01aa50e 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -19,11 +19,15 @@ protected static function booted() $service->fileStorages()->delete(); }); } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } - public function isGzipEnabled() + public function is_stripprefix_enabled() + { + return data_get($this, 'is_stripprefix_enabled', true); + } + public function is_gzip_enabled() { return data_get($this, 'is_gzip_enabled', true); } diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index 31bd2786d..c3f4cc278 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -17,11 +17,11 @@ protected static function booted() $service->fileStorages()->delete(); }); } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } - public function isGzipEnabled() + public function is_gzip_enabled() { return true; } diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php index 174397baa..2f2be6757 100644 --- a/app/Models/StandaloneMariadb.php +++ b/app/Models/StandaloneMariadb.php @@ -100,7 +100,7 @@ public function link() } return null; } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } @@ -126,7 +126,7 @@ public function portsMappingsArray(): Attribute ); } - public function getDbUrl(bool $useInternal = false): string + public function get_db_url(bool $useInternal = false): string { if ($this->is_public && !$useInternal) { return "mysql://{$this->mariadb_user}:{$this->mariadb_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->mariadb_database}"; diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php index d6efaaa1e..cb10f8f55 100644 --- a/app/Models/StandaloneMongodb.php +++ b/app/Models/StandaloneMongodb.php @@ -92,7 +92,7 @@ public function team() { return data_get($this, 'environment.project.team'); } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } @@ -142,7 +142,7 @@ public function type(): string { return 'standalone-mongodb'; } - public function getDbUrl(bool $useInternal = false) + public function get_db_url(bool $useInternal = false) { if ($this->is_public && !$useInternal) { return "mongodb://{$this->mongo_initdb_root_username}:{$this->mongo_initdb_root_password}@{$this->destination->server->getIp}:{$this->public_port}/?directConnection=true"; diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php index f317196aa..c2d2b5c6f 100644 --- a/app/Models/StandaloneMysql.php +++ b/app/Models/StandaloneMysql.php @@ -105,7 +105,7 @@ public function type(): string return 'standalone-mysql'; } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } @@ -127,7 +127,7 @@ public function portsMappingsArray(): Attribute ); } - public function getDbUrl(bool $useInternal = false): string + public function get_db_url(bool $useInternal = false): string { if ($this->is_public && !$useInternal) { return "mysql://{$this->mysql_user}:{$this->mysql_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->mysql_database}"; diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index 3d2317159..ad0dce108 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -97,7 +97,7 @@ public function link() } return null; } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } @@ -126,7 +126,7 @@ public function type(): string { return 'standalone-postgresql'; } - public function getDbUrl(bool $useInternal = false): string + public function get_db_url(bool $useInternal = false): string { if ($this->is_public && !$useInternal) { return "postgres://{$this->postgres_user}:{$this->postgres_password}@{$this->destination->server->getIp}:{$this->public_port}/{$this->postgres_db}"; diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index 6b6b6c415..c1b1d1390 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -96,7 +96,7 @@ public function link() } return null; } - public function isLogDrainEnabled() + public function is_log_drain_enabled() { return data_get($this, 'is_log_drain_enabled', false); } @@ -122,7 +122,7 @@ public function type(): string { return 'standalone-redis'; } - public function getDbUrl(bool $useInternal = false): string + public function get_db_url(bool $useInternal = false): string { if ($this->is_public && !$useInternal) { return "redis://:{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0"; diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 008bd4d7f..237a12d74 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -215,7 +215,7 @@ function generateServiceSpecificFqdns(ServiceApplication|Application $resource, } return $payload; } -function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?string $service_name = null) +function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_https_enabled = false, $onlyPort = null, ?Collection $serviceLabels = null, ?bool $is_gzip_enabled = true, ?bool $is_stripprefix_enabled = true, ?string $service_name = null) { $labels = collect([]); $labels->push('traefik.enable=true'); @@ -281,8 +281,10 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ $labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port"); } if ($path !== '/') { - $labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}"); - $middlewares = collect(["{$https_label}-stripprefix"]); + if ($is_stripprefix_enabled) { + $labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}"); + $middlewares = collect(["{$https_label}-stripprefix"]); + } if ($is_gzip_enabled) { $middlewares->push('gzip'); } @@ -334,8 +336,10 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_ $labels->push("traefik.http.routers.{$http_label}.service={$http_label}"); } if ($path !== '/') { - $labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}"); - $middlewares = collect(["{$http_label}-stripprefix"]); + if ($is_stripprefix_enabled) { + $labels->push("traefik.http.middlewares.{$http_label}-stripprefix.stripprefix.prefixes={$path}"); + $middlewares = collect(["{$http_label}-stripprefix"]); + } if ($is_gzip_enabled) { $middlewares->push('gzip'); } @@ -392,7 +396,14 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview $domains = Str::of(data_get($application, 'fqdn'))->explode(','); } // Add Traefik labels no matter which proxy is selected - $labels = $labels->merge(fqdnLabelsForTraefik($appUuid, $domains, $application->settings->is_force_https_enabled, $onlyPort)); + $labels = $labels->merge(fqdnLabelsForTraefik( + uuid: $appUuid, + domains: $domains, + onlyPort: $onlyPort, + is_force_https_enabled: $application->is_force_https_enabled(), + is_gzip_enabled: $application->is_gzip_enabled(), + is_stripprefix_enabled: $application->is_stripprefix_enabled() + )); } return $labels->all(); } diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 47dd8b284..47cc57c35 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1047,10 +1047,17 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceLabels = $serviceLabels->merge($defaultLabels); if (!$isDatabase && $fqdns->count() > 0) { if ($fqdns) { - $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($resource->uuid, $fqdns, true, serviceLabels: $serviceLabels, is_gzip_enabled: $savedService->isGzipEnabled(), service_name: $serviceName)); + $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik( + uuid: $resource->uuid, + domains: $fqdns, + is_force_https_enabled: true, + serviceLabels: $serviceLabels, + is_gzip_enabled: $savedService->is_gzip_enabled(), + is_stripprefix_enabled: $savedService->is_stripprefix_enabled(), + service_name: $serviceName)); } } - if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) { + if ($resource->server->is_log_drain_enabled() && $savedService->is_log_drain_enabled()) { data_set($service, 'logging', [ 'driver' => 'fluentd', 'options' => [ @@ -1494,7 +1501,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $defaultLabels = defaultLabels($resource->id, $containerName, $pull_request_id, type: 'application'); $serviceLabels = $serviceLabels->merge($defaultLabels); - if ($server->isLogDrainEnabled() && $resource->isLogDrainEnabled()) { + if ($server->is_log_drain_enabled() && $resource->is_log_drain_enabled()) { data_set($service, 'logging', [ 'driver' => 'fluentd', 'options' => [ diff --git a/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php b/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php new file mode 100644 index 000000000..1787a07eb --- /dev/null +++ b/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php @@ -0,0 +1,36 @@ +boolean('is_gzip_enabled')->default(true); + $table->boolean('is_stripprefix_enabled')->default(true); + }); + Schema::table('service_applications', function (Blueprint $table) { + $table->boolean('is_stripprefix_enabled')->default(true); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('application_settings', function (Blueprint $table) { + $table->dropColumn('is_gzip_enabled'); + $table->dropColumn('is_stripprefix_enabled'); + }); + Schema::table('service_applications', function (Blueprint $table) { + $table->dropColumn('is_stripprefix_enabled'); + }); + } +}; diff --git a/resources/views/livewire/project/application/advanced.blade.php b/resources/views/livewire/project/application/advanced.blade.php index e88fb8a27..d4566a2b2 100644 --- a/resources/views/livewire/project/application/advanced.blade.php +++ b/resources/views/livewire/project/application/advanced.blade.php @@ -20,6 +20,11 @@ helper="The deployed container will have the same name ({{ $application->uuid }}). You will lose the rolling update feature!" instantSave id="application.settings.is_consistent_container_name_enabled" label="Consistent Container Names" /> + +

Logs

@if (!$application->settings->is_raw_compose_deployment_enabled) Advanced
+ helper="You can disable gzip compression if you want. Some services are compressing data by default. In this case, you do not need this." /> + diff --git a/resources/views/livewire/server/log-drains.blade.php b/resources/views/livewire/server/log-drains.blade.php index 496f60369..3936bf5f9 100644 --- a/resources/views/livewire/server/log-drains.blade.php +++ b/resources/views/livewire/server/log-drains.blade.php @@ -12,7 +12,7 @@
- @if ($server->isLogDrainEnabled()) + @if ($server->is_log_drain_enabled())
- @if ($server->isLogDrainEnabled()) + @if ($server->is_log_drain_enabled())
- @if ($server->isLogDrainEnabled()) + @if ($server->is_log_drain_enabled()) Date: Mon, 4 Mar 2024 10:46:53 +0100 Subject: [PATCH 09/11] Update proxy configuration layout --- resources/views/livewire/server/proxy.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/server/proxy.blade.php b/resources/views/livewire/server/proxy.blade.php index a5944fc1a..e87ad573a 100644 --- a/resources/views/livewire/server/proxy.blade.php +++ b/resources/views/livewire/server/proxy.blade.php @@ -25,7 +25,7 @@
@if ($proxy_settings) -
+
From c20aa0b2564d41f17554d46099c6e1e0a5b2f66c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 4 Mar 2024 11:01:14 +0100 Subject: [PATCH 10/11] Refactor method names to use camel case --- app/Actions/Database/StartMariadb.php | 2 +- app/Actions/Database/StartMongodb.php | 2 +- app/Actions/Database/StartMysql.php | 2 +- app/Actions/Database/StartPostgresql.php | 2 +- app/Actions/Database/StartRedis.php | 2 +- app/Console/Kernel.php | 2 +- app/Jobs/ApplicationDeploymentJob.php | 2 +- app/Livewire/Project/Application/Advanced.php | 10 +++++----- app/Livewire/Project/Database/Mariadb/General.php | 2 +- app/Livewire/Project/Database/Mongodb/General.php | 2 +- app/Livewire/Project/Database/Mysql/General.php | 2 +- app/Livewire/Project/Database/Postgresql/General.php | 2 +- app/Livewire/Project/Database/Redis/General.php | 2 +- app/Livewire/Project/Service/Database.php | 2 +- .../Project/Service/ServiceApplicationView.php | 2 +- app/Livewire/Server/LogDrains.php | 2 +- app/Models/Application.php | 8 ++++---- app/Models/Server.php | 2 +- app/Models/ServiceApplication.php | 6 +++--- app/Models/ServiceDatabase.php | 10 +++++++--- app/Models/StandaloneMariadb.php | 2 +- app/Models/StandaloneMongodb.php | 2 +- app/Models/StandaloneMysql.php | 2 +- app/Models/StandalonePostgresql.php | 2 +- app/Models/StandaloneRedis.php | 2 +- bootstrap/helpers/docker.php | 6 +++--- bootstrap/helpers/shared.php | 9 +++++---- ...244_add_gzip_enabled_and_stripprefix_settings.php | 8 ++++++++ resources/views/livewire/server/log-drains.blade.php | 6 +++--- templates/compose/changedetection.yaml | 3 --- templates/service-templates.json | 12 ++++++++++++ 31 files changed, 71 insertions(+), 49 deletions(-) diff --git a/app/Actions/Database/StartMariadb.php b/app/Actions/Database/StartMariadb.php index 3274566a1..8dca584f2 100644 --- a/app/Actions/Database/StartMariadb.php +++ b/app/Actions/Database/StartMariadb.php @@ -71,7 +71,7 @@ public function handle(StandaloneMariadb $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { + if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Actions/Database/StartMongodb.php b/app/Actions/Database/StartMongodb.php index 75bfe3ed3..ef04a9be8 100644 --- a/app/Actions/Database/StartMongodb.php +++ b/app/Actions/Database/StartMongodb.php @@ -78,7 +78,7 @@ public function handle(StandaloneMongodb $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { + if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Actions/Database/StartMysql.php b/app/Actions/Database/StartMysql.php index 4a8edc1e2..3b47483a3 100644 --- a/app/Actions/Database/StartMysql.php +++ b/app/Actions/Database/StartMysql.php @@ -71,7 +71,7 @@ public function handle(StandaloneMysql $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { + if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Actions/Database/StartPostgresql.php b/app/Actions/Database/StartPostgresql.php index ea5de10da..844f81c31 100644 --- a/app/Actions/Database/StartPostgresql.php +++ b/app/Actions/Database/StartPostgresql.php @@ -77,7 +77,7 @@ public function handle(StandalonePostgresql $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { + if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { ray('Log Drain Enabled'); $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 692c14c1c..e1a8eef41 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -81,7 +81,7 @@ public function handle(StandaloneRedis $database) if (!is_null($this->database->limits_cpuset)) { data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } - if ($this->database->destination->server->is_log_drain_enabled() && $this->database->is_log_drain_enabled()) { + if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { $docker_compose['services'][$container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Console/Kernel.php b/app/Console/Kernel.php index 4599dd5a4..e92c602cf 100644 --- a/app/Console/Kernel.php +++ b/app/Console/Kernel.php @@ -77,7 +77,7 @@ private function check_resources($schedule) // ray('dispatching container status job in ' . $randomSeconds . ' seconds'); // dispatch($job); // })->name('container-status-' . $server->id)->everyMinute()->onOneServer(); - if ($server->is_log_drain_enabled()) { + if ($server->isLogDrainEnabled()) { $schedule->job(new CheckLogDrainContainerJob($server))->everyMinute()->onOneServer(); // $schedule // ->call(function () use ($server) { diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 29709d675..0dedfd596 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1185,7 +1185,7 @@ private function generate_compose_file() } else { $docker_compose['services'][$this->container_name]['labels'] = $labels; } - if ($this->server->is_log_drain_enabled() && $this->application->is_log_drain_enabled()) { + if ($this->server->isLogDrainEnabled() && $this->application->isLogDrainEnabled()) { $docker_compose['services'][$this->container_name]['logging'] = [ 'driver' => 'fluentd', 'options' => [ diff --git a/app/Livewire/Project/Application/Advanced.php b/app/Livewire/Project/Application/Advanced.php index 442f5488a..278cab5a1 100644 --- a/app/Livewire/Project/Application/Advanced.php +++ b/app/Livewire/Project/Application/Advanced.php @@ -29,14 +29,14 @@ class Advanced extends Component 'application.settings.gpu_options' => 'string|required', ]; public function mount() { - $this->is_force_https_enabled = $this->application->settings->is_force_https_enabled; - $this->is_gzip_enabled = $this->application->settings->is_gzip_enabled; - $this->is_stripprefix_enabled = $this->application->settings->is_stripprefix_enabled; + $this->is_force_https_enabled = $this->application->isForceHttpsEnabled(); + $this->is_gzip_enabled = $this->application->isGzipEnabled(); + $this->is_stripprefix_enabled = $this->application->isStripprefixEnabled(); } public function instantSave() { - if ($this->application->is_log_drain_enabled()) { - if (!$this->application->destination->server->is_log_drain_enabled()) { + if ($this->application->isLogDrainEnabled()) { + if (!$this->application->destination->server->isLogDrainEnabled()) { $this->application->settings->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on this server.'); return; diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php index 9e0a0c5fc..a4b6e1883 100644 --- a/app/Livewire/Project/Database/Mariadb/General.php +++ b/app/Livewire/Project/Database/Mariadb/General.php @@ -53,7 +53,7 @@ public function mount() } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->is_log_drain_enabled()) { + if (!$this->database->destination->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php index 5c9f9cb47..c1b55b1e7 100644 --- a/app/Livewire/Project/Database/Mongodb/General.php +++ b/app/Livewire/Project/Database/Mongodb/General.php @@ -52,7 +52,7 @@ public function mount() public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->is_log_drain_enabled()) { + if (!$this->database->destination->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php index f67641b31..cab11e8ce 100644 --- a/app/Livewire/Project/Database/Mysql/General.php +++ b/app/Livewire/Project/Database/Mysql/General.php @@ -54,7 +54,7 @@ public function mount() public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->is_log_drain_enabled()) { + if (!$this->database->destination->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index 102557351..3237c1be3 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -60,7 +60,7 @@ public function mount() } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->is_log_drain_enabled()) { + if (!$this->database->destination->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index ee02239af..a894626b0 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -46,7 +46,7 @@ public function mount() } public function instantSaveAdvanced() { try { - if (!$this->database->destination->server->is_log_drain_enabled()) { + if (!$this->database->destination->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index c86c54da2..8dec97852 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -36,7 +36,7 @@ public function mount() } public function instantSaveAdvanced() { - if (!$this->database->service->destination->server->is_log_drain_enabled()) { + if (!$this->database->service->destination->server->isLogDrainEnabled()) { $this->database->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Project/Service/ServiceApplicationView.php b/app/Livewire/Project/Service/ServiceApplicationView.php index 9a4738c9f..29bd796fd 100644 --- a/app/Livewire/Project/Service/ServiceApplicationView.php +++ b/app/Livewire/Project/Service/ServiceApplicationView.php @@ -30,7 +30,7 @@ public function instantSave() } public function instantSaveAdvanced() { - if (!$this->application->service->destination->server->is_log_drain_enabled()) { + if (!$this->application->service->destination->server->isLogDrainEnabled()) { $this->application->is_log_drain_enabled = false; $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); return; diff --git a/app/Livewire/Server/LogDrains.php b/app/Livewire/Server/LogDrains.php index 605aa25b5..4eca682d4 100644 --- a/app/Livewire/Server/LogDrains.php +++ b/app/Livewire/Server/LogDrains.php @@ -54,7 +54,7 @@ public function configureLogDrain() { try { InstallLogDrain::run($this->server); - if (!$this->server->is_log_drain_enabled()) { + if (!$this->server->isLogDrainEnabled()) { $this->dispatch('serverRefresh'); $this->dispatch('success', 'Log drain service stopped.'); return; diff --git a/app/Models/Application.php b/app/Models/Application.php index 24a61eca9..8fa4979d7 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -80,15 +80,15 @@ public function is_github_based(): bool } return false; } - public function is_force_https_enabled() + public function isForceHttpsEnabled() { return data_get($this, 'settings.is_force_https_enabled', false); } - public function is_stripprefix_enabled() + public function isStripprefixEnabled() { return data_get($this, 'settings.is_stripprefix_enabled', true); } - public function is_gzip_enabled() + public function isGzipEnabled() { return data_get($this, 'settings.is_gzip_enabled', true); } @@ -493,7 +493,7 @@ public function workdir() { return application_configuration_dir() . "/{$this->uuid}"; } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'settings.is_log_drain_enabled', false); } diff --git a/app/Models/Server.php b/app/Models/Server.php index 5293bdd99..4028109e2 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -405,7 +405,7 @@ public function isFunctional() { return $this->settings->is_reachable && $this->settings->is_usable && !$this->settings->force_disabled; } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return $this->settings->is_logdrain_newrelic_enabled || $this->settings->is_logdrain_highlight_enabled || $this->settings->is_logdrain_axiom_enabled || $this->settings->is_logdrain_custom_enabled; } diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index 8a01aa50e..37f7d9c9c 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -19,15 +19,15 @@ protected static function booted() $service->fileStorages()->delete(); }); } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } - public function is_stripprefix_enabled() + public function isStripprefixEnabled() { return data_get($this, 'is_stripprefix_enabled', true); } - public function is_gzip_enabled() + public function isGzipEnabled() { return data_get($this, 'is_gzip_enabled', true); } diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index c3f4cc278..9375fe807 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -17,13 +17,17 @@ protected static function booted() $service->fileStorages()->delete(); }); } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } - public function is_gzip_enabled() + public function isStripprefixEnabled() { - return true; + return data_get($this, 'is_stripprefix_enabled', true); + } + public function isGzipEnabled() + { + return data_get($this, 'is_gzip_enabled', true); } public function type() { diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php index 2f2be6757..eb465e989 100644 --- a/app/Models/StandaloneMariadb.php +++ b/app/Models/StandaloneMariadb.php @@ -100,7 +100,7 @@ public function link() } return null; } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php index cb10f8f55..a8aab4e42 100644 --- a/app/Models/StandaloneMongodb.php +++ b/app/Models/StandaloneMongodb.php @@ -92,7 +92,7 @@ public function team() { return data_get($this, 'environment.project.team'); } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php index c2d2b5c6f..89155d3ec 100644 --- a/app/Models/StandaloneMysql.php +++ b/app/Models/StandaloneMysql.php @@ -105,7 +105,7 @@ public function type(): string return 'standalone-mysql'; } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index ad0dce108..0b7589e81 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -97,7 +97,7 @@ public function link() } return null; } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index c1b1d1390..2b623f28d 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -96,7 +96,7 @@ public function link() } return null; } - public function is_log_drain_enabled() + public function isLogDrainEnabled() { return data_get($this, 'is_log_drain_enabled', false); } diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index 237a12d74..5fd43daa9 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -400,9 +400,9 @@ function generateLabelsApplication(Application $application, ?ApplicationPreview uuid: $appUuid, domains: $domains, onlyPort: $onlyPort, - is_force_https_enabled: $application->is_force_https_enabled(), - is_gzip_enabled: $application->is_gzip_enabled(), - is_stripprefix_enabled: $application->is_stripprefix_enabled() + is_force_https_enabled: $application->isForceHttpsEnabled(), + is_gzip_enabled: $application->isGzipEnabled(), + is_stripprefix_enabled: $application->isStripprefixEnabled() )); } return $labels->all(); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 47cc57c35..9bb2c164a 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1052,12 +1052,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal domains: $fqdns, is_force_https_enabled: true, serviceLabels: $serviceLabels, - is_gzip_enabled: $savedService->is_gzip_enabled(), - is_stripprefix_enabled: $savedService->is_stripprefix_enabled(), + is_gzip_enabled: $savedService->isGzipEnabled(), + is_stripprefix_enabled: $savedService->isStripprefixEnabled(), service_name: $serviceName)); + } } - if ($resource->server->is_log_drain_enabled() && $savedService->is_log_drain_enabled()) { + if ($resource->server->isLogDrainEnabled() && $savedService->isLogDrainEnabled()) { data_set($service, 'logging', [ 'driver' => 'fluentd', 'options' => [ @@ -1501,7 +1502,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $defaultLabels = defaultLabels($resource->id, $containerName, $pull_request_id, type: 'application'); $serviceLabels = $serviceLabels->merge($defaultLabels); - if ($server->is_log_drain_enabled() && $resource->is_log_drain_enabled()) { + if ($server->isLogDrainEnabled() && $resource->isLogDrainEnabled()) { data_set($service, 'logging', [ 'driver' => 'fluentd', 'options' => [ diff --git a/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php b/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php index 1787a07eb..5d23da60e 100644 --- a/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php +++ b/database/migrations/2024_03_04_092244_add_gzip_enabled_and_stripprefix_settings.php @@ -18,6 +18,10 @@ public function up(): void Schema::table('service_applications', function (Blueprint $table) { $table->boolean('is_stripprefix_enabled')->default(true); }); + Schema::table('service_databases', function (Blueprint $table) { + $table->boolean('is_gzip_enabled')->default(true); + $table->boolean('is_stripprefix_enabled')->default(true); + }); } /** @@ -32,5 +36,9 @@ public function down(): void Schema::table('service_applications', function (Blueprint $table) { $table->dropColumn('is_stripprefix_enabled'); }); + Schema::table('service_databases', function (Blueprint $table) { + $table->dropColumn('is_gzip_enabled'); + $table->dropColumn('is_stripprefix_enabled'); + }); } }; diff --git a/resources/views/livewire/server/log-drains.blade.php b/resources/views/livewire/server/log-drains.blade.php index 3936bf5f9..496f60369 100644 --- a/resources/views/livewire/server/log-drains.blade.php +++ b/resources/views/livewire/server/log-drains.blade.php @@ -12,7 +12,7 @@
- @if ($server->is_log_drain_enabled()) + @if ($server->isLogDrainEnabled())
- @if ($server->is_log_drain_enabled()) + @if ($server->isLogDrainEnabled())
- @if ($server->is_log_drain_enabled()) + @if ($server->isLogDrainEnabled()) Date: Mon, 4 Mar 2024 11:17:05 +0100 Subject: [PATCH 11/11] Update slogan and logo for changedetection service --- public/svgs/changedetection.png | Bin 0 -> 31507 bytes templates/compose/changedetection.yaml | 3 ++- templates/service-templates.json | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) create mode 100644 public/svgs/changedetection.png diff --git a/public/svgs/changedetection.png b/public/svgs/changedetection.png new file mode 100644 index 0000000000000000000000000000000000000000..b2e86f1d091b5973bfe1bb73950936562d525455 GIT binary patch literal 31507 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 literal 0 HcmV?d00001 diff --git a/templates/compose/changedetection.yaml b/templates/compose/changedetection.yaml index 5b92fcc0d..be8a4e0d2 100644 --- a/templates/compose/changedetection.yaml +++ b/templates/compose/changedetection.yaml @@ -1,6 +1,7 @@ # documentation: https://github.com/dgtlmoon/changedetection.io/ -# slogan: Website change detection monitor and notifications +# slogan: Website change detection monitor and notifications. # tags: web, alert, monitor +# logo: svgs/changedetection.png services: changedetection: diff --git a/templates/service-templates.json b/templates/service-templates.json index 9ff38d831..b2cc462e9 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -53,14 +53,14 @@ }, "changedetection": { "documentation": "https:\/\/github.com\/dgtlmoon\/changedetection.io\/", - "slogan": "Website change detection monitor and notifications", + "slogan": "Website change detection monitor and notifications.", "compose": "c2VydmljZXM6CiAgY2hhbmdlZGV0ZWN0aW9uOgogICAgaW1hZ2U6IGdoY3IuaW8vZGd0bG1vb24vY2hhbmdlZGV0ZWN0aW9uLmlvCiAgICB2b2x1bWVzOgogICAgICAtICdjaGFuZ2VkZXRlY3Rpb24tZGF0YTovZGF0YXN0b3JlJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0NIQU5HRURFVEVDVElPTgogICAgICAtIFBVSUQ9MTAwMAogICAgICAtIFBHSUQ9MTAwMAogICAgICAtIEJBU0VfVVJMPSRTRVJWSUNFX0ZRRE5fQ0hBTkdFREVURUNUSU9OCiAgICAgIC0gJ1BMQVlXUklHSFRfRFJJVkVSX1VSTD13czovL3BsYXl3cmlnaHQtY2hyb21lOjMwMDAvP3N0ZWFsdGg9MSYtLWRpc2FibGUtd2ViLXNlY3VyaXR5PXRydWUnCiAgICAgIC0gSElERV9SRUZFUkVSPXRydWUKICAgIGRlcGVuZHNfb246CiAgICAgIHBsYXl3cmlnaHQtY2hyb21lOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkCiAgcGxheXdyaWdodC1jaHJvbWU6CiAgICBpbWFnZTogJ2RndGxtb29uL3NvY2twdXBwZXRicm93c2VyOmxhdGVzdCcKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTQ1JFRU5fV0lEVEg9MTkyMAogICAgICAtIFNDUkVFTl9IRUlHSFQ9MTAyNAogICAgICAtIFNDUkVFTl9ERVBUSD0xNgogICAgICAtIE1BWF9DT05DVVJSRU5UX0NIUk9NRV9QUk9DRVNTRVM9MTAK", "tags": [ "web", "alert", "monitor" ], - "logo": "svgs\/unknown.svg", + "logo": "svgs\/changedetection.png", "minversion": "0.0.0" }, "code-server": {