From 1651845e208ce37645773e9d3fd7380c59d52d70 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 11:54:56 +0200 Subject: [PATCH 01/15] version++ --- config/sentry.php | 2 +- config/version.php | 2 +- versions.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/sentry.php b/config/sentry.php index 338151754..abbd727b5 100644 --- a/config/sentry.php +++ b/config/sentry.php @@ -7,7 +7,7 @@ return [ // 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.64', + 'release' => '4.0.0-beta.65', // 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 765ef0e18..e13d2a071 100644 --- a/config/version.php +++ b/config/version.php @@ -1,3 +1,3 @@ Date: Wed, 4 Oct 2023 14:40:04 +0200 Subject: [PATCH 02/15] feat: multiselect removable resources --- app/Console/Commands/ResourcesDelete.php | 32 +++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/app/Console/Commands/ResourcesDelete.php b/app/Console/Commands/ResourcesDelete.php index d230aa927..c9ad0f0e9 100644 --- a/app/Console/Commands/ResourcesDelete.php +++ b/app/Console/Commands/ResourcesDelete.php @@ -8,6 +8,7 @@ use App\Models\StandalonePostgresql; use Illuminate\Console\Command; use function Laravel\Prompts\confirm; +use function Laravel\Prompts\multiselect; use function Laravel\Prompts\select; class ResourcesDelete extends Command @@ -50,16 +51,18 @@ class ResourcesDelete extends Command $this->error('There are no applications to delete.'); return; } - $application = select( + $applicationsToDelete = multiselect( 'What application do you want to delete?', $applications->pluck('name')->toArray(), ); - $application = $applications->where('name', $application)->first(); - $confirmed = confirm("Are you sure you want to delete {$application->name}?"); + $confirmed = confirm("Are you sure you want to delete all selected resources?"); if (!$confirmed) { return; } - $application->delete(); + foreach ($applicationsToDelete as $application) { + $toDelete = $applications->where('name', $application)->first(); + $toDelete->delete(); + } } private function deleteDatabase() { @@ -68,16 +71,19 @@ class ResourcesDelete extends Command $this->error('There are no databases to delete.'); return; } - $database = select( + $databasesToDelete = multiselect( 'What database do you want to delete?', $databases->pluck('name')->toArray(), ); - $database = $databases->where('name', $database)->first(); - $confirmed = confirm("Are you sure you want to delete {$database->name}?"); + $confirmed = confirm("Are you sure you want to delete all selected resources?"); if (!$confirmed) { return; } - $database->delete(); + foreach ($databasesToDelete as $database) { + $toDelete = $databases->where('name', $database)->first(); + $toDelete->delete(); + } + } private function deleteService() { @@ -86,15 +92,17 @@ class ResourcesDelete extends Command $this->error('There are no services to delete.'); return; } - $service = select( + $servicesToDelete = multiselect( 'What service do you want to delete?', $services->pluck('name')->toArray(), ); - $service = $services->where('name', $service)->first(); - $confirmed = confirm("Are you sure you want to delete {$service->name}?"); + $confirmed = confirm("Are you sure you want to delete all selected resources?"); if (!$confirmed) { return; } - $service->delete(); + foreach ($servicesToDelete as $service) { + $toDelete = $services->where('name', $service)->first(); + $toDelete->delete(); + } } } From 5a90eed7ef27e155d3f5753c082bf28ead7a8535 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 14:40:26 +0200 Subject: [PATCH 03/15] fix: compose parser updated --- app/Models/Service.php | 17 +++++++++++++---- bootstrap/helpers/services.php | 9 +++++++-- bootstrap/helpers/shared.php | 1 + 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/app/Models/Service.php b/app/Models/Service.php index 8440dee6a..ddf200946 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -408,6 +408,7 @@ class Service extends BaseModel $savedService->save(); } } + data_forget($service, "environment.$variableName"); continue; } if ($value?->startsWith('$')) { @@ -422,10 +423,17 @@ class Service extends BaseModel $forService = $value->afterLast('_'); $generatedValue = null; if ($command->value() === 'FQDN' || $command->value() === 'URL') { - $fqdn = generateFqdn($this->server, $containerName); + if (Str::lower($forService) === $serviceName) { + $fqdn = generateFqdn($this->server, $containerName); + } else { + $fqdn = generateFqdn($this->server, Str::lower($forService) . '-' . $this->uuid); + } if ($foundEnv) { $fqdn = data_get($foundEnv, 'value'); } else { + if ($command->value() === 'URL') { + $fqdn = Str::of($fqdn)->after('://')->value(); + } EnvironmentVariable::create([ 'key' => $key, 'value' => $fqdn, @@ -434,10 +442,11 @@ class Service extends BaseModel 'is_preview' => false, ]); } - if (!$isDatabase) { - $savedService->fqdn = $fqdn; - $savedService->save(); + if ($command->value() === 'FQDN') { + $savedService->fqdn = $fqdn; + $savedService->save(); + } } } else { switch ($command) { diff --git a/bootstrap/helpers/services.php b/bootstrap/helpers/services.php index 2590049ad..762b83563 100644 --- a/bootstrap/helpers/services.php +++ b/bootstrap/helpers/services.php @@ -137,13 +137,18 @@ function updateCompose($resource) // Update FQDN $variableName = "SERVICE_FQDN_" . Str::of($resource->name)->upper(); - ray($variableName); $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); if ($generatedEnv) { $generatedEnv->value = $resource->fqdn; $generatedEnv->save(); } - + $variableName = "SERVICE_URL_" . Str::of($resource->name)->upper(); + $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first(); + if ($generatedEnv) { + $url = Str::of($resource->fqdn)->after('://'); + $generatedEnv->value = $url; + $generatedEnv->save(); + } $dockerComposeRaw = Yaml::dump($dockerCompose, 10, 2); $resource->service->docker_compose_raw = $dockerComposeRaw; diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 01f9d55ae..eee61602d 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -14,6 +14,7 @@ use Illuminate\Mail\Message; use Illuminate\Notifications\Messages\MailMessage; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Cache; +use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Http; use Illuminate\Support\Facades\Mail; use Illuminate\Support\Facades\Route; From 45f9def0f6c0464164be5e54ab59b312efb9a4ff Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 14:40:33 +0200 Subject: [PATCH 04/15] fix: dev compose files --- app/Http/Livewire/Dev/Compose.php | 28 +++++++++++++++++++ .../docker-compose-appwrite.yaml | 0 .../{ => compose}/docker-compose-fider.yaml | 0 .../{ => compose}/docker-compose-ghost.yaml | 10 +++++-- .../docker-compose-plausible.yaml | 0 .../docker-compose-postgres.yaml | 0 .../docker-compose-uptime-kuma.yaml | 0 .../{ => compose}/docker-compose-weird.yaml | 0 .../views/livewire/dev/compose.blade.php | 13 +++++++++ routes/web.php | 5 +++- 10 files changed, 53 insertions(+), 3 deletions(-) create mode 100644 app/Http/Livewire/Dev/Compose.php rename examples/{ => compose}/docker-compose-appwrite.yaml (100%) rename examples/{ => compose}/docker-compose-fider.yaml (100%) rename examples/{ => compose}/docker-compose-ghost.yaml (73%) rename examples/{ => compose}/docker-compose-plausible.yaml (100%) rename examples/{ => compose}/docker-compose-postgres.yaml (100%) rename examples/{ => compose}/docker-compose-uptime-kuma.yaml (100%) rename examples/{ => compose}/docker-compose-weird.yaml (100%) create mode 100644 resources/views/livewire/dev/compose.blade.php diff --git a/app/Http/Livewire/Dev/Compose.php b/app/Http/Livewire/Dev/Compose.php new file mode 100644 index 000000000..d3a0ee4e5 --- /dev/null +++ b/app/Http/Livewire/Dev/Compose.php @@ -0,0 +1,28 @@ +services = getServiceTemplates(); + } + public function setService(string $selected) { + $this->base64 = data_get($this->services, $selected . '.compose'); + if ($this->base64) { + $this->compose = base64_decode($this->base64); + } + } + public function updatedCompose($value) { + $this->base64 = base64_encode($value); + } + public function render() + { + return view('livewire.dev.compose'); + } +} diff --git a/examples/docker-compose-appwrite.yaml b/examples/compose/docker-compose-appwrite.yaml similarity index 100% rename from examples/docker-compose-appwrite.yaml rename to examples/compose/docker-compose-appwrite.yaml diff --git a/examples/docker-compose-fider.yaml b/examples/compose/docker-compose-fider.yaml similarity index 100% rename from examples/docker-compose-fider.yaml rename to examples/compose/docker-compose-fider.yaml diff --git a/examples/docker-compose-ghost.yaml b/examples/compose/docker-compose-ghost.yaml similarity index 73% rename from examples/docker-compose-ghost.yaml rename to examples/compose/docker-compose-ghost.yaml index eb55f86f6..ee88bd974 100644 --- a/examples/docker-compose-ghost.yaml +++ b/examples/compose/docker-compose-ghost.yaml @@ -11,7 +11,8 @@ services: - database__connection__password=$SERVICE_PASSWORD_MYSQL - database__connection__database=${MYSQL_DATABASE-ghost} depends_on: - - mysql + mysql: + condition: service_healthy mysql: image: mysql:8.0 volumes: @@ -20,4 +21,9 @@ services: - MYSQL_USER=${SERVICE_USER_MYSQL} - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL} - MYSQL_DATABASE=${MYSQL_DATABASE} - - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQL_ROOT} + - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT} + healthcheck: + test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] + interval: 5s + timeout: 5s + retries: 10 diff --git a/examples/docker-compose-plausible.yaml b/examples/compose/docker-compose-plausible.yaml similarity index 100% rename from examples/docker-compose-plausible.yaml rename to examples/compose/docker-compose-plausible.yaml diff --git a/examples/docker-compose-postgres.yaml b/examples/compose/docker-compose-postgres.yaml similarity index 100% rename from examples/docker-compose-postgres.yaml rename to examples/compose/docker-compose-postgres.yaml diff --git a/examples/docker-compose-uptime-kuma.yaml b/examples/compose/docker-compose-uptime-kuma.yaml similarity index 100% rename from examples/docker-compose-uptime-kuma.yaml rename to examples/compose/docker-compose-uptime-kuma.yaml diff --git a/examples/docker-compose-weird.yaml b/examples/compose/docker-compose-weird.yaml similarity index 100% rename from examples/docker-compose-weird.yaml rename to examples/compose/docker-compose-weird.yaml diff --git a/resources/views/livewire/dev/compose.blade.php b/resources/views/livewire/dev/compose.blade.php new file mode 100644 index 000000000..5d7ad1be1 --- /dev/null +++ b/resources/views/livewire/dev/compose.blade.php @@ -0,0 +1,13 @@ +
+

Compose

+
All kinds of compose files.
+

Services

+ @foreach ($services as $serviceName => $value) + {{ Str::headline($serviceName) }} + @endforeach +

Base64 En/Decode

+ Copy Base64 Compose +
+ +
+
diff --git a/routes/web.php b/routes/web.php index 8fe8bd1db..1ebbb46fd 100644 --- a/routes/web.php +++ b/routes/web.php @@ -9,6 +9,7 @@ use App\Http\Controllers\ServerController; use App\Http\Livewire\Boarding\Index as BoardingIndex; use App\Http\Livewire\Project\Service\Index as ServiceIndex; use App\Http\Livewire\Project\Service\Show as ServiceShow; +use App\Http\Livewire\Dev\Compose as Compose; use App\Http\Livewire\Dashboard; use App\Http\Livewire\Project\Shared\Logs; use App\Http\Livewire\Server\All; @@ -29,6 +30,9 @@ use Laravel\Fortify\Contracts\FailedPasswordResetLinkRequestResponse; use Laravel\Fortify\Contracts\SuccessfulPasswordResetLinkRequestResponse; use Laravel\Fortify\Fortify; +if (isDev()) { + Route::get('/dev/compose', Compose::class)->name('dev.compose'); +} Route::post('/forgot-password', function (Request $request) { if (is_transactional_emails_active()) { $arrayOfRequest = $request->only(Fortify::email()); @@ -94,7 +98,6 @@ Route::middleware(['auth'])->group(function () { Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}', ServiceIndex::class)->name('project.service'); Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}/{service_name}', ServiceShow::class)->name('project.service.show'); Route::get('/project/{project_uuid}/{environment_name}/service/{service_uuid}/{service_name}/logs', Logs::class)->name('project.service.logs'); - }); Route::middleware(['auth'])->group(function () { From d4a7d0d25fdb6e36476f86aa84ec357e285361a8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 15:39:23 +0200 Subject: [PATCH 05/15] fix: traefik labels for multiport deployments --- bootstrap/helpers/docker.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/bootstrap/helpers/docker.php b/bootstrap/helpers/docker.php index e22a3596c..142754801 100644 --- a/bootstrap/helpers/docker.php +++ b/bootstrap/helpers/docker.php @@ -157,11 +157,13 @@ function fqdnLabelsForTraefik(Collection $domains, $container_name, $is_force_ht $path = $url->getPath(); $schema = $url->getScheme(); $port = $url->getPort(); - $slug = Str::slug($host . $path); - - $http_label = "{$container_name}-{$slug}-http"; - $https_label = "{$container_name}-{$slug}-https"; + $http_label = "{$container_name}-http"; + $https_label = "{$container_name}-https"; + if ($port) { + $http_label = "{$http_label}-{$port}"; + $https_label = "{$https_label}-{$port}"; + } if ($schema === 'https') { // Set labels for https $labels->push("traefik.http.routers.{$https_label}.rule=Host(`{$host}`) && PathPrefix(`{$path}`)"); From af69575b29e5ce09963f79b7ef6ac40d322007c0 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 15:40:08 +0200 Subject: [PATCH 06/15] fix: remove SERVICE_ stuff from raw compose feat: multiport predefined compose fix: use predefined name as prefix for fqdn --- app/Models/Service.php | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/app/Models/Service.php b/app/Models/Service.php index ddf200946..2757d3584 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -140,7 +140,7 @@ class Service extends BaseModel } $definedNetwork = collect([$this->uuid]); - $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS) { + $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $yaml) { $serviceVolumes = collect(data_get($service, 'volumes', [])); $servicePorts = collect(data_get($service, 'ports', [])); $serviceNetworks = collect(data_get($service, 'networks', [])); @@ -266,7 +266,7 @@ class Service extends BaseModel // Collect/create/update volumes if ($serviceVolumes->count() > 0) { - $serviceVolumes = $serviceVolumes->map(function ($volume) use ($savedService, $topLevelVolumes, $isNew) { + $serviceVolumes = $serviceVolumes->map(function ($volume) use ($savedService, $topLevelVolumes, $isNew, $yaml) { $type = null; $source = null; $target = null; @@ -384,9 +384,20 @@ class Service extends BaseModel $value = Str::of($variable); } if ($key->startsWith('SERVICE_FQDN')) { - if (is_null(data_get($savedService, 'fqdn'))) { - $fqdn = generateFqdn($this->server, $containerName); - if (substr_count($key->value(), '_') === 2) { + if ($isNew) { + $name = $key->after('SERVICE_FQDN_')->beforeLast('_')->lower(); + $fqdn = generateFqdn($this->server, "{$name->value()}-{$this->uuid}"); + if (substr_count($key->value(), '_') === 3) { + // SERVICE_FQDN_UMAMI_1000 + $port = $key->afterLast('_'); + } else { + // SERVICE_FQDN_UMAMI + $port = null; + } + if ($port) { + $fqdn = "$fqdn:$port"; + } + if (substr_count($key->value(), '_') >= 2) { if (is_null($value)) { $value = Str::of('/'); } @@ -403,12 +414,27 @@ class Service extends BaseModel } $fqdn = "$fqdn$path"; } + // } else if (substr_count($key->value(), '_') === 3) { + // if (is_null($value)) { + // $value = Str::of('/'); + // } + // $path = $value->value(); + // } if (!$isDatabase) { + if ($savedService->fqdn) { + $fqdn = $savedService->fqdn . ',' . $fqdn; + } else { + $fqdn = $fqdn; + } $savedService->fqdn = $fqdn; $savedService->save(); } } data_forget($service, "environment.$variableName"); + $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName"); + if (count(data_get($yaml, 'services.' . $serviceName . '.environment')) === 0) { + $yaml = data_forget($yaml, "services.$serviceName.environment"); + } continue; } if ($value?->startsWith('$')) { @@ -522,14 +548,12 @@ class Service extends BaseModel $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($fqdns, $containerName, true)); } } - data_set($service, 'labels', $serviceLabels->toArray()); data_forget($service, 'is_database'); data_set($service, 'restart', RESTART_MODE); data_set($service, 'container_name', $containerName); data_forget($service, 'volumes.*.content'); data_forget($service, 'volumes.*.isDirectory'); - // Remove unnecessary variables from service.environment $withoutServiceEnvs = collect([]); collect(data_get($service, 'environment'))->each(function ($value, $key) use ($withoutServiceEnvs) { @@ -538,6 +562,7 @@ class Service extends BaseModel } }); data_set($service, 'environment', $withoutServiceEnvs->toArray()); + $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); return $service; }); $finalServices = [ @@ -546,7 +571,6 @@ class Service extends BaseModel 'volumes' => $topLevelVolumes->toArray(), 'networks' => $topLevelNetworks->toArray(), ]; - $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); $this->docker_compose = Yaml::dump($finalServices, 10, 2); $this->save(); $this->saveComposeConfigs(); From 32bb2780f2e107b2b46ae3646c3621740493dca9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 15:43:29 +0200 Subject: [PATCH 07/15] rename composes --- ...ocker-compose-appwrite.yaml => appwrite.yaml} | 0 .../{docker-compose-fider.yaml => fider.yaml} | 0 .../{docker-compose-ghost.yaml => ghost.yaml} | 0 examples/compose/minio.yaml | 16 ++++++++++++++++ ...ker-compose-plausible.yaml => plausible.yaml} | 0 ...ocker-compose-postgres.yaml => postgres.yaml} | 0 ...compose-uptime-kuma.yaml => uptime-kuma.yaml} | 0 .../{docker-compose-weird.yaml => weird.yaml} | 0 8 files changed, 16 insertions(+) rename examples/compose/{docker-compose-appwrite.yaml => appwrite.yaml} (100%) rename examples/compose/{docker-compose-fider.yaml => fider.yaml} (100%) rename examples/compose/{docker-compose-ghost.yaml => ghost.yaml} (100%) create mode 100644 examples/compose/minio.yaml rename examples/compose/{docker-compose-plausible.yaml => plausible.yaml} (100%) rename examples/compose/{docker-compose-postgres.yaml => postgres.yaml} (100%) rename examples/compose/{docker-compose-uptime-kuma.yaml => uptime-kuma.yaml} (100%) rename examples/compose/{docker-compose-weird.yaml => weird.yaml} (100%) diff --git a/examples/compose/docker-compose-appwrite.yaml b/examples/compose/appwrite.yaml similarity index 100% rename from examples/compose/docker-compose-appwrite.yaml rename to examples/compose/appwrite.yaml diff --git a/examples/compose/docker-compose-fider.yaml b/examples/compose/fider.yaml similarity index 100% rename from examples/compose/docker-compose-fider.yaml rename to examples/compose/fider.yaml diff --git a/examples/compose/docker-compose-ghost.yaml b/examples/compose/ghost.yaml similarity index 100% rename from examples/compose/docker-compose-ghost.yaml rename to examples/compose/ghost.yaml diff --git a/examples/compose/minio.yaml b/examples/compose/minio.yaml new file mode 100644 index 000000000..62ee47765 --- /dev/null +++ b/examples/compose/minio.yaml @@ -0,0 +1,16 @@ +services: + minio: + image: quay.io/minio/minio:RELEASE.2023-09-30T07-02-29Z + command: server /data --console-address ":9001" + environment: + SERVICE_FQDN_MINIO_9000: + SERVICE_FQDN_CONSOLE_9001: + MINIO_ROOT_USER: $SERVICE_USER_MINIO + MINIO_ROOT_PASSWORD: $SERVICE_PASSWORD_MINIO + volumes: + - minio-data:/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] + interval: 5s + timeout: 20s + retries: 10 diff --git a/examples/compose/docker-compose-plausible.yaml b/examples/compose/plausible.yaml similarity index 100% rename from examples/compose/docker-compose-plausible.yaml rename to examples/compose/plausible.yaml diff --git a/examples/compose/docker-compose-postgres.yaml b/examples/compose/postgres.yaml similarity index 100% rename from examples/compose/docker-compose-postgres.yaml rename to examples/compose/postgres.yaml diff --git a/examples/compose/docker-compose-uptime-kuma.yaml b/examples/compose/uptime-kuma.yaml similarity index 100% rename from examples/compose/docker-compose-uptime-kuma.yaml rename to examples/compose/uptime-kuma.yaml diff --git a/examples/compose/docker-compose-weird.yaml b/examples/compose/weird.yaml similarity index 100% rename from examples/compose/docker-compose-weird.yaml rename to examples/compose/weird.yaml From 2971e360d7dbc3c57113c16d568323437e23987b Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Wed, 4 Oct 2023 18:06:25 +0200 Subject: [PATCH 08/15] revert last commits --- app/Models/Service.php | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/app/Models/Service.php b/app/Models/Service.php index 2757d3584..8f4e3a72a 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -140,7 +140,7 @@ class Service extends BaseModel } $definedNetwork = collect([$this->uuid]); - $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS, $yaml) { + $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew, $generatedServiceFQDNS) { $serviceVolumes = collect(data_get($service, 'volumes', [])); $servicePorts = collect(data_get($service, 'ports', [])); $serviceNetworks = collect(data_get($service, 'networks', [])); @@ -266,7 +266,7 @@ class Service extends BaseModel // Collect/create/update volumes if ($serviceVolumes->count() > 0) { - $serviceVolumes = $serviceVolumes->map(function ($volume) use ($savedService, $topLevelVolumes, $isNew, $yaml) { + $serviceVolumes = $serviceVolumes->map(function ($volume) use ($savedService, $topLevelVolumes) { $type = null; $source = null; $target = null; @@ -430,11 +430,11 @@ class Service extends BaseModel $savedService->save(); } } - data_forget($service, "environment.$variableName"); - $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName"); - if (count(data_get($yaml, 'services.' . $serviceName . '.environment')) === 0) { - $yaml = data_forget($yaml, "services.$serviceName.environment"); - } + // data_forget($service, "environment.$variableName"); + // $yaml = data_forget($yaml, "services.$serviceName.environment.$variableName"); + // if (count(data_get($yaml, 'services.' . $serviceName . '.environment')) === 0) { + // $yaml = data_forget($yaml, "services.$serviceName.environment"); + // } continue; } if ($value?->startsWith('$')) { @@ -562,7 +562,6 @@ class Service extends BaseModel } }); data_set($service, 'environment', $withoutServiceEnvs->toArray()); - $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); return $service; }); $finalServices = [ @@ -571,6 +570,7 @@ class Service extends BaseModel 'volumes' => $topLevelVolumes->toArray(), 'networks' => $topLevelNetworks->toArray(), ]; + $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); $this->docker_compose = Yaml::dump($finalServices, 10, 2); $this->save(); $this->saveComposeConfigs(); From 4075572dbc4b9fc20bb2ae6335572a836dafec87 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 08:32:20 +0200 Subject: [PATCH 09/15] fix: visible version number --- resources/views/components/version.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/version.blade.php b/resources/views/components/version.blade.php index 3ed4586da..a5ffdac32 100644 --- a/resources/views/components/version.blade.php +++ b/resources/views/components/version.blade.php @@ -1,2 +1,2 @@ -merge(['class' => 'text-xs cursor-pointer opacity-20 hover:opacity-100 hover:text-white z-50']) }} +merge(['class' => 'text-xs cursor-pointer opacity-60 hover:opacity-100 hover:text-white z-50']) }} href="https://github.com/coollabsio/coolify/releases/tag/v{{ config('version') }}">v{{ config('version') }} From 1c8f92d3b7625bd76cafe0d49a75615bb4c06bcc Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 08:40:17 +0200 Subject: [PATCH 10/15] fix: remove SERVICE_ from deployable compose --- app/Models/Service.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/app/Models/Service.php b/app/Models/Service.php index 8f4e3a72a..13b7173c1 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -414,12 +414,7 @@ class Service extends BaseModel } $fqdn = "$fqdn$path"; } - // } else if (substr_count($key->value(), '_') === 3) { - // if (is_null($value)) { - // $value = Str::of('/'); - // } - // $path = $value->value(); - // } + if (!$isDatabase) { if ($savedService->fqdn) { $fqdn = $savedService->fqdn . ',' . $fqdn; @@ -557,8 +552,10 @@ class Service extends BaseModel // Remove unnecessary variables from service.environment $withoutServiceEnvs = collect([]); collect(data_get($service, 'environment'))->each(function ($value, $key) use ($withoutServiceEnvs) { - if (!Str::of($key)->startsWith('$SERVICE_')) { - $withoutServiceEnvs->put($key, $value); + if (!Str::of($key)->startsWith('$SERVICE_') && !Str::of($value)->startsWith('SERVICE_')) { + $k = Str::of($value)->before("="); + $v = Str::of($value)->after("="); + $withoutServiceEnvs->put($k->value(), $v->value()); } }); data_set($service, 'environment', $withoutServiceEnvs->toArray()); From 91db1953ff1d16f53e0764d3704a1435a6ae8174 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 08:46:26 +0200 Subject: [PATCH 11/15] fix: delete event to deleting --- app/Models/Project.php | 2 +- app/Models/Service.php | 2 +- app/Models/StandalonePostgresql.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/Models/Project.php b/app/Models/Project.php index 9bcd2a0fe..13f86bf66 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -22,7 +22,7 @@ class Project extends BaseModel 'project_id' => $project->id, ]); }); - static::deleted(function ($project) { + static::deleting(function ($project) { $project->environments()->delete(); $project->settings()->delete(); }); diff --git a/app/Models/Service.php b/app/Models/Service.php index 13b7173c1..30e292945 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -16,7 +16,7 @@ class Service extends BaseModel protected static function booted() { - static::deleted(function ($service) { + static::deleting(function ($service) { $storagesToDelete = collect([]); foreach ($service->applications()->get() as $application) { instant_remote_process(["docker rm -f {$application->name}-{$service->uuid}"], $service->server, false); diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index ed270862b..d177e9ab9 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -28,7 +28,7 @@ class StandalonePostgresql extends BaseModel 'is_readonly' => true ]); }); - static::deleted(function ($database) { + static::deleting(function ($database) { // Stop Container instant_remote_process( ["docker rm -f {$database->uuid}"], From 5ae16b195c61ea918fabd7a7b0740adf6314a117 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 08:50:01 +0200 Subject: [PATCH 12/15] remove ray --- app/Http/Livewire/Boarding/Index.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/Http/Livewire/Boarding/Index.php b/app/Http/Livewire/Boarding/Index.php index d124e6a89..a0c5038e0 100644 --- a/app/Http/Livewire/Boarding/Index.php +++ b/app/Http/Livewire/Boarding/Index.php @@ -76,7 +76,6 @@ uZx9iFkCELtxrh31QJ68AAAAEXNhaWxANzZmZjY2ZDJlMmRkAQIDBA== Team::find(currentTeam()->id)->update([ 'show_boarding' => false ]); - ray(currentTeam()); refreshSession(); return redirect()->route('dashboard'); } From b08f525bd4eebb1ae5be4bcc1165240e47fc2764 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 08:54:03 +0200 Subject: [PATCH 13/15] fix: move dev data to volumes to prevent permission issues --- docker-compose.dev.yml | 14 ++++++++++---- scripts/run | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index cefdec07f..0d78d257b 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -34,14 +34,14 @@ services: POSTGRES_DB: "${DB_DATABASE:-coolify}" POSTGRES_HOST_AUTH_METHOD: "trust" volumes: - - /data/coolify/_volumes/database/:/var/lib/postgresql/data + - coolify-pg-data-dev:/var/lib/postgresql/data redis: ports: - "${FORWARD_REDIS_PORT:-6379}:6379" env_file: - .env volumes: - - /data/coolify/_volumes/redis/:/data + - coolify-redis-data-dev:/data vite: image: node:19 working_dir: /var/www/html @@ -56,7 +56,7 @@ services: volumes: - /:/host - /var/run/docker.sock:/var/run/docker.sock - - /data/coolify/:/data/coolify + - coolify-data-dev:/data/coolify mailpit: image: "axllent/mailpit:latest" container_name: coolify-mail @@ -76,6 +76,12 @@ services: MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" volumes: - - /data/coolify/_volumes/minio/:/data + - coolify-minio-data-dev:/data networks: - coolify + +volumes: + coolify-data-dev: + coolify-pg-data-dev: + coolify-redis-data-dev: + coolify-minio-data-dev: diff --git a/scripts/run b/scripts/run index 85eed74d4..33c5da621 100755 --- a/scripts/run +++ b/scripts/run @@ -21,8 +21,8 @@ function help { } function setup:dev { - docker exec coolify bash -c "composer install" docker exec coolify bash -c "php artisan key:generate" + docker exec coolify bash -c "composer install" docker exec coolify bash -c "php artisan migrate:fresh --seed" } function sync:v3 { From 762af66cbf8d0a985097743205e6aef9c67ff080 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 10:48:26 +0200 Subject: [PATCH 14/15] add deprecated templates in dev --- bootstrap/helpers/shared.php | 3 +++ templates/deprecated.json | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index eee61602d..5406926d8 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -426,6 +426,9 @@ function getServiceTemplates() if (isDev()) { $services = File::get(base_path('templates/service-templates.json')); $services = collect(json_decode($services))->sortKeys(); + $deprecated = File::get(base_path('templates/deprecated.json')); + $deprecated = collect(json_decode($deprecated))->sortKeys(); + $services = $services->merge($deprecated); } else { $services = Http::get(config('constants.services.official')); if ($services->failed()) { diff --git a/templates/deprecated.json b/templates/deprecated.json index 59c1be455..5ed9d92a0 100644 --- a/templates/deprecated.json +++ b/templates/deprecated.json @@ -3,5 +3,5 @@ "documentation": "https://plausible.io/docs", "slogan": "A lighweight and open-source website analytics tool.", "compose": "dmVyc2lvbjogJzMuMycKc2VydmljZXM6CiAgcGxhdXNpYmxlX2RiOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNC1hbHBpbmUnCiAgICByZXN0YXJ0OiBhbHdheXMKICAgIHZvbHVtZXM6CiAgICAgIC0gJy9ldGMvZGF0YS9wbGF1c2libGUvZGItZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kUE9TVEdSRVNfUEFTU1dPUkQKICBwbGF1c2libGVfZXZlbnRzX2RiOgogICAgaW1hZ2U6ICdjbGlja2hvdXNlL2NsaWNraG91c2Utc2VydmVyOjIzLjMuNy41LWFscGluZScKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgdm9sdW1lczoKICAgICAgLSAnL2V0Yy9kYXRhL3BsYXVzaWJsZS9ldmVudC1kYXRhOi92YXIvbGliL2NsaWNraG91c2UnCiAgICAgIC0gdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogL2V0Yy9kYXRhL3BsYXVzaWJsZS9jbGlja2hvdXNlL2NsaWNraG91c2UtY29uZmlnLnhtbAogICAgICAgIHRhcmdldDogL2V0Yy9jbGlja2hvdXNlLXNlcnZlci9jb25maWcuZC9sb2dnaW5nLnhtbAogICAgICAgIHJlYWRfb25seTogdHJ1ZQogICAgICAgIGNvbnRlbnQ6ID4tCiAgICAgICAgICA8Y2xpY2tob3VzZT48cHJvZmlsZXM+PGRlZmF1bHQ+PGxvZ19xdWVyaWVzPjA8L2xvZ19xdWVyaWVzPjxsb2dfcXVlcnlfdGhyZWFkcz4wPC9sb2dfcXVlcnlfdGhyZWFkcz48L2RlZmF1bHQ+PC9wcm9maWxlcz48L2NsaWNraG91c2U+CiAgICAgIC0gdHlwZTogYmluZAogICAgICAgIHNvdXJjZTogL2V0Yy9kYXRhL3BsYXVzaWJsZS9jbGlja2hvdXNlL2NsaWNraG91c2UtdXNlci1jb25maWcueG1sCiAgICAgICAgdGFyZ2V0OiAvZXRjL2NsaWNraG91c2Utc2VydmVyL3VzZXJzLmQvbG9nZ2luZy54bWwKICAgICAgICByZWFkX29ubHk6IHRydWUKICAgICAgICBjb250ZW50OiA+LQogICAgICAgICAgPGNsaWNraG91c2U+PGxvZ2dlcj48bGV2ZWw+d2FybmluZzwvbGV2ZWw+PGNvbnNvbGU+dHJ1ZTwvY29uc29sZT48L2xvZ2dlcj48cXVlcnlfdGhyZWFkX2xvZwogICAgICAgICAgcmVtb3ZlPSJyZW1vdmUiLz48cXVlcnlfbG9nIHJlbW92ZT0icmVtb3ZlIi8+PHRleHRfbG9nCiAgICAgICAgICByZW1vdmU9InJlbW92ZSIvPjx0cmFjZV9sb2cgcmVtb3ZlPSJyZW1vdmUiLz48bWV0cmljX2xvZwogICAgICAgICAgcmVtb3ZlPSJyZW1vdmUiLz48YXN5bmNocm9ub3VzX21ldHJpY19sb2cKICAgICAgICAgIHJlbW92ZT0icmVtb3ZlIi8+PHNlc3Npb25fbG9nIHJlbW92ZT0icmVtb3ZlIi8+PHBhcnRfbG9nCiAgICAgICAgICByZW1vdmU9InJlbW92ZSIvPjwvY2xpY2tob3VzZT4KICAgIHVsaW1pdHM6CiAgICAgICAgbm9maWxlOgogICAgICAgICAgc29mdDogMjYyMTQ0CiAgICAgICAgICBoYXJkOiAyNjIxNDQKICBwbGF1c2libGU6CiAgICBpbWFnZTogJ3BsYXVzaWJsZS9hbmFseXRpY3M6djIuMCcKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgY29tbWFuZDogJ3NoIC1jICJzbGVlcCAxMCAmJiAvZW50cnlwb2ludC5zaCBkYiBjcmVhdGVkYiAmJiAvZW50cnlwb2ludC5zaCBkYiBtaWdyYXRlICYmIC9lbnRyeXBvaW50LnNoIHJ1biInCiAgICBkZXBlbmRzX29uOgogICAgICAtIHBsYXVzaWJsZV9kYgogICAgICAtIHBsYXVzaWJsZV9ldmVudHNfZGIKICAgIHBvcnRzOgogICAgICAtICc4MDAwOjgwMDAnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRUNSRVRfS0VZX0JBU0U9JFNFQ1JFVF9LRVlfQkFTRQogICAgICAtIERBVEFCQVNFX1VSTD0kREFUQUJBU0VfVVJMCiAgICAgIC0gJ0NMSUNLSE9VU0VfREFUQUJBU0VfVVJMPWh0dHA6Ly9wbGF1c2libGVfZXZlbnRzX2RiOjgxMjMvcGxhdXNpYmxlX2V2ZW50c19kYicKICAgICAgLSBNQUlMRVJfQURBUFRFUj0kTUFJTEVSX0FEQVBURVIKICAgICAgLSBTRU5ER1JJRF9BUElfS0VZPSRTRU5ER1JJRF9BUElfS0VZCiAgICAgIC0gR09PR0xFX0NMSUVOVF9JRD0kR09PR0xFX0NMSUVOVF9JRAogICAgICAtIEdPT0dMRV9DTElFTlRfU0VDUkVUPSRHT09HTEVfQ0xJRU5UX1NFQ1JFVAogICAgICAtIERJU0FCTEVfUkVHSVNUUkFUSU9OPSRESVNBQkxFX1JFR0lTVFJBVElPTgogICAgICAtIEJBU0VfVVJMPSRCQVNFX1VSTAogICAgICAtIExPR19GQUlMRURfTE9HSU5fQVRURU1QVFM9JExPR19GQUlMRURfTE9HSU5fQVRURU1QVFMK" - }, + } } From e2e64e36a0dba7af41eb48418596be0a4c67a2a8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Thu, 5 Oct 2023 10:58:08 +0200 Subject: [PATCH 15/15] feat: disable service, required version --- bootstrap/helpers/shared.php | 7 ++++ resources/css/app.css | 3 ++ .../livewire/project/new/select.blade.php | 36 ++++++++++++------- 3 files changed, 34 insertions(+), 12 deletions(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 5406926d8..0d4971a5f 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -429,6 +429,13 @@ function getServiceTemplates() $deprecated = File::get(base_path('templates/deprecated.json')); $deprecated = collect(json_decode($deprecated))->sortKeys(); $services = $services->merge($deprecated); + $version = config('version'); + $services = $services->map(function ($service) use ($version) { + if (version_compare($version, data_get($service,'minVersion', '0.0.0'), '<')) { + $service->disabled = true; + } + return $service; + }); } else { $services = Http::get(config('constants.services.official')); if ($services->failed()) { diff --git a/resources/css/app.css b/resources/css/app.css index 7703ef608..ea7109d3d 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -55,6 +55,9 @@ a { .box { @apply flex items-center p-2 transition-colors cursor-pointer min-h-16 bg-coolgray-200 hover:bg-coollabs-100 hover:text-white hover:no-underline min-w-[24rem]; } +.box-without-bg { + @apply flex items-center p-2 transition-colors min-h-16 hover:text-white hover:no-underline min-w-[24rem]; +} .lds-heart { animation: lds-heart 1.2s infinite cubic-bezier(0.215, 0.61, 0.355, 1); diff --git a/resources/views/livewire/project/new/select.blade.php b/resources/views/livewire/project/new/select.blade.php index a673b693a..8e4b9d54c 100644 --- a/resources/views/livewire/project/new/select.blade.php +++ b/resources/views/livewire/project/new/select.blade.php @@ -95,19 +95,31 @@ @else @foreach ($services as $serviceName => $service) - + You need to upgrade to {{ data_get($service, 'minVersion') }} to use this service. + + + @else + + @endif @endforeach @endif