diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 38b57a9db..4c0da8d4d 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1331,9 +1331,11 @@ class ApplicationDeploymentJob implements ShouldQueue, ShouldBeEncrypted if ($this->pull_request_id !== 0) { $labels = collect(generateLabelsApplication($this->application, $this->preview)); } - $labels = $labels->map(function ($value, $key) { - return escapeDollarSign($value); - }); + if ($this->application->settings->is_container_label_escape_enabled) { + $labels = $labels->map(function ($value, $key) { + return escapeDollarSign($value); + }); + } $labels = $labels->merge(defaultLabels($this->application->id, $this->application->uuid, $this->pull_request_id))->toArray(); // Check for custom HEALTHCHECK diff --git a/app/Livewire/Project/Application/General.php b/app/Livewire/Project/Application/General.php index 885f84247..66c59cff5 100644 --- a/app/Livewire/Project/Application/General.php +++ b/app/Livewire/Project/Application/General.php @@ -22,6 +22,7 @@ class General extends Component public ?string $git_commit_sha = null; public string $build_pack; public ?string $ports_exposes = null; + public bool $is_container_label_escape_enabled = true; public $customLabels; public bool $labelsChanged = false; @@ -74,6 +75,7 @@ class General extends Component 'application.post_deployment_command_container' => 'nullable', 'application.settings.is_static' => 'boolean|required', 'application.settings.is_build_server_enabled' => 'boolean|required', + 'application.settings.is_container_label_escape_enabled' => 'boolean|required', 'application.watch_paths' => 'nullable', ]; protected $validationAttributes = [ @@ -109,6 +111,7 @@ class General extends Component 'application.docker_compose_custom_build_command' => 'Docker compose custom build command', 'application.settings.is_static' => 'Is static', 'application.settings.is_build_server_enabled' => 'Is build server enabled', + 'application.settings.is_container_label_escape_enabled' => 'Is container label escape enabled', 'application.watch_paths' => 'Watch paths', ]; public function mount() @@ -124,6 +127,7 @@ class General extends Component } $this->parsedServiceDomains = $this->application->docker_compose_domains ? json_decode($this->application->docker_compose_domains, true) : []; $this->ports_exposes = $this->application->ports_exposes; + $this->is_container_label_escape_enabled = $this->application->settings->is_container_label_escape_enabled; $this->customLabels = $this->application->parseContainerLabels(); if (!$this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') { $this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n"); @@ -145,7 +149,7 @@ class General extends Component $this->application->settings->save(); $this->dispatch('success', 'Settings saved.'); $this->application->refresh(); - if ($this->ports_exposes !== $this->application->ports_exposes) { + if ($this->ports_exposes !== $this->application->ports_exposes || $this->is_container_label_escape_enabled !== $this->application->settings->is_container_label_escape_enabled) { $this->resetDefaultLabels(false); } } @@ -204,6 +208,9 @@ class General extends Component $this->application->docker_compose_domains = json_encode($this->parsedServiceDomains); $this->application->save(); $this->dispatch('success', 'Domain generated.'); + if ($this->application->build_pack === 'dockercompose') { + $this->loadComposeFile(); + } return $domain; } public function updatedApplicationBaseDirectory() @@ -257,9 +264,12 @@ class General extends Component { $this->customLabels = str(implode("|", generateLabelsApplication($this->application)))->replace("|", "\n"); $this->ports_exposes = $this->application->ports_exposes; - + $this->is_container_label_escape_enabled = $this->application->settings->is_container_label_escape_enabled; $this->application->custom_labels = base64_encode($this->customLabels); $this->application->save(); + if ($this->application->build_pack === 'dockercompose') { + $this->loadComposeFile(); + } } public function checkFqdns($showToaster = true) @@ -300,11 +310,11 @@ class General extends Component if ($this->application->build_pack === 'dockercompose' && $this->initialDockerComposeLocation !== $this->application->docker_compose_location) { $compose_return = $this->loadComposeFile(); if ($compose_return instanceof \Livewire\Features\SupportEvents\Event) { - return; + return; } } $this->validate(); - if ($this->ports_exposes !== $this->application->ports_exposes) { + if ($this->ports_exposes !== $this->application->ports_exposes || $this->is_container_label_escape_enabled !== $this->application->settings->is_container_label_escape_enabled) { $this->resetDefaultLabels(); } if (data_get($this->application, 'build_pack') === 'dockerimage') { diff --git a/app/Livewire/Project/Service/EditCompose.php b/app/Livewire/Project/Service/EditCompose.php index 0f9c449f9..d6e867956 100644 --- a/app/Livewire/Project/Service/EditCompose.php +++ b/app/Livewire/Project/Service/EditCompose.php @@ -12,6 +12,7 @@ class EditCompose extends Component protected $rules = [ 'service.docker_compose_raw' => 'required', 'service.docker_compose' => 'required', + 'service.is_container_label_escape_enabled' => 'required', ]; public function mount() { @@ -23,6 +24,14 @@ class EditCompose extends Component $this->dispatch('info', "Saving new docker compose..."); $this->dispatch('saveCompose', $this->service->docker_compose_raw); } + public function instantSave() + { + $this->validate([ + 'service.is_container_label_escape_enabled' => 'required', + ]); + $this->service->save(['is_container_label_escape_enabled' => $this->service->is_container_label_escape_enabled]); + $this->dispatch('success', "Service updated successfully"); + } public function render() { return view('livewire.project.service.edit-compose'); diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 183d9d2ec..7a960066c 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -1174,9 +1174,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal ] ]); } - $serviceLabels = $serviceLabels->map(function ($value, $key) { - return escapeDollarSign($value); - }); + if ($serviceLabels->count() > 0) { + if ($resource->is_container_label_escape_enabled) { + $serviceLabels = $serviceLabels->map(function ($value, $key) { + return escapeDollarSign($value); + }); + } + } data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); if (!data_get($service, 'restart')) { @@ -1279,11 +1283,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal $serviceLabels->push("$removedLabelName=$removedLabel"); } } - if ($serviceLabels->count() > 0) { - $serviceLabels = $serviceLabels->map(function ($value, $key) { - return escapeDollarSign($value); - }); - } + $baseName = generateApplicationContainerName($resource, $pull_request_id); $containerName = "$serviceName-$baseName"; if (count($serviceVolumes) > 0) { @@ -1663,6 +1663,13 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal ] ]); } + if ($serviceLabels->count() > 0) { + if ($resource->settings->is_container_label_escape_enabled) { + $serviceLabels = $serviceLabels->map(function ($value, $key) { + return escapeDollarSign($value); + }); + } + } data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); if (!data_get($service, 'restart')) { diff --git a/database/migrations/2024_05_15_151236_add_container_escape_toggle.php b/database/migrations/2024_05_15_151236_add_container_escape_toggle.php new file mode 100644 index 000000000..aa1384518 --- /dev/null +++ b/database/migrations/2024_05_15_151236_add_container_escape_toggle.php @@ -0,0 +1,34 @@ +boolean('is_container_label_escape_enabled')->default(true); + }); + Schema::table('services', function (Blueprint $table) { + $table->boolean('is_container_label_escape_enabled')->default(true); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('application_settings', function (Blueprint $table) { + $table->dropColumn('is_container_label_escape_enabled'); + }); + Schema::table('services', function (Blueprint $table) { + $table->dropColumn('is_container_label_escape_enabled'); + }); + } +}; diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index 37869621d..b9a971124 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -219,6 +219,11 @@ @endif +
+ +
{{-- --}} @endif @@ -242,8 +247,15 @@ @endif - - Are you sure you want to reset the labels to Coolify generated labels?
It could break the proxy configuration after you restart the container. +
+ +
+ + Are you sure you want to reset the labels to Coolify generated labels?
It could break the proxy + configuration after you restart the container.
@endif diff --git a/resources/views/livewire/project/service/edit-compose.blade.php b/resources/views/livewire/project/service/edit-compose.blade.php index 83931e863..ab9948cf7 100644 --- a/resources/views/livewire/project/service/edit-compose.blade.php +++ b/resources/views/livewire/project/service/edit-compose.blade.php @@ -3,6 +3,11 @@ prevent name collision.
To see the actual volume names, check the Deployable Compose file, or go to Storage menu. +
+ +
@@ -14,10 +19,10 @@
- Show Deployable Compose + Show Deployable Compose
- Show Source + Show Source Compose