diff --git a/app/Http/Livewire/Project/Service/FileStorage.php b/app/Http/Livewire/Project/Service/FileStorage.php index 39e250f66..4341c6f51 100644 --- a/app/Http/Livewire/Project/Service/FileStorage.php +++ b/app/Http/Livewire/Project/Service/FileStorage.php @@ -29,9 +29,7 @@ public function mount() $this->fs_path = Str::of($this->fs_path)->after('.'); $this->fs_path = $this->service->service->workdir() . $this->fs_path . "/" . $file; } - if ($this->fileStorage->is_directory) { - $this->fs_path = Str::of($this->fileStorage->fs_path); - } + } public function submit() { diff --git a/app/Http/Livewire/Project/Service/Index.php b/app/Http/Livewire/Project/Service/Index.php index 0a09484ff..c3c6c57c8 100644 --- a/app/Http/Livewire/Project/Service/Index.php +++ b/app/Http/Livewire/Project/Service/Index.php @@ -29,12 +29,10 @@ public function refreshStack() $this->applications = $this->service->applications->sort(); $this->applications->each(function ($application) { $application->refresh(); - $application->configuration_required = $application->configurationRequired(); }); $this->databases = $this->service->databases->sort(); $this->databases->each(function ($database) { $database->refresh(); - $database->configuration_required = $database->configurationRequired(); }); } public function mount() diff --git a/app/Models/Service.php b/app/Models/Service.php index f282df71f..166f40fd6 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -277,6 +277,7 @@ public function parse(bool $isNew = false): Collection $source = null; $target = null; $content = null; + $isDirectory = false; if (is_string($volume)) { $source = Str::of($volume)->before(':'); $target = Str::of($volume)->after(':')->beforeLast(':'); @@ -290,12 +291,18 @@ public function parse(bool $isNew = false): Collection $source = data_get_str($volume, 'source'); $target = data_get_str($volume, 'target'); $content = data_get($volume, 'content'); + $isDirectory = (bool) data_get($volume, 'isDirectory', false); + $foundConfig = $savedService->fileStorages()->whereMountPath($target)->first(); + if ($foundConfig) { + $content = data_get($foundConfig, 'content'); + $isDirectory = (bool) data_get($foundConfig, 'is_directory'); + } } if ($type->value() === 'bind') { if ($source->value() === "/var/run/docker.sock") { continue; } - if ($source->value() === '/tmp' || $source->value() === '/tmp/' ) { + if ($source->value() === '/tmp' || $source->value() === '/tmp/') { continue; } LocalFileVolume::updateOrCreate( @@ -308,6 +315,7 @@ public function parse(bool $isNew = false): Collection 'fs_path' => $source, 'mount_path' => $target, 'content' => $content, + 'is_directory' => $isDirectory, 'resource_id' => $savedService->id, 'resource_type' => get_class($savedService) ] @@ -328,6 +336,7 @@ public function parse(bool $isNew = false): Collection ] ); } + $savedService->saveFileVolumes(); } } @@ -367,7 +376,7 @@ public function parse(bool $isNew = false): Collection if (is_null(data_get($savedService, 'fqdn'))) { $sslip = $this->sslip($this->server); $fqdn = "http://$containerName.$sslip"; - if (substr_count($key->value(),'_') === 2 && $key->contains("=")) { + if (substr_count($key->value(), '_') === 2 && $key->contains("=")) { $path = $value->value(); if ($generatedServiceFQDNS->count() > 0) { $alreadyGenerated = $generatedServiceFQDNS->has($key->value()); @@ -498,6 +507,7 @@ public function parse(bool $isNew = false): Collection 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([]); @@ -515,452 +525,11 @@ public function parse(bool $isNew = false): Collection 'volumes' => $topLevelVolumes->toArray(), 'networks' => $topLevelNetworks->toArray(), ]; - data_forget($yaml, 'services.*.volumes.*.content'); $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); $this->docker_compose = Yaml::dump($finalServices, 10, 2); $this->save(); $this->saveComposeConfigs(); return collect([]); - // $services = collect($services)->map(function ($service, $serviceName) use ($composeVolumes, $composeNetworks, $definedNetwork, $envs, $volumes, $ports, $isNew, $configuration) { - // $container_name = "$serviceName-{$this->uuid}"; - // $isDatabase = false; - // $serviceVariables = collect(data_get($service, 'environment', [])); - - // // Add env_file with at least .env to the service - // $envFile = collect(data_get($service, 'env_file', [])); - // if ($envFile->count() > 0) { - // if (!$envFile->contains('.env')) { - // $envFile->push('.env'); - // } - // } else { - // $envFile = collect(['.env']); - // } - // data_set($service, 'env_file', $envFile->toArray()); - - // // Decide if the service is a database - // $image = data_get($service, 'image'); - // if ($image) { - // $imageName = Str::of($image)->before(':'); - // if (collect(DATABASE_DOCKER_IMAGES)->contains($imageName)) { - // $isDatabase = true; - // data_set($service, 'is_database', true); - // } - // } - // if ($isDatabase) { - // $savedService = ServiceDatabase::where([ - // 'name' => $serviceName, - // 'service_id' => $this->id - // ])->first(); - // } else { - // $savedService = ServiceApplication::where([ - // 'name' => $serviceName, - // 'service_id' => $this->id - // ])->first(); - // } - // if ($isNew || is_null($savedService)) { - // if ($isDatabase) { - // $savedService = ServiceDatabase::create([ - // 'name' => $serviceName, - // 'image' => $image, - // 'service_id' => $this->id - // ]); - // } else { - // $savedService = ServiceApplication::create([ - // 'name' => $serviceName, - // 'fqdn' => $this->generateFqdn($serviceVariables, $serviceName, $configuration), - // 'image' => $image, - // 'service_id' => $this->id - // ]); - // } - // if ($configuration->count() > 0) { - // foreach ($configuration as $requiredFqdn) { - // $requiredFqdn = (array)$requiredFqdn; - // $name = data_get($requiredFqdn, 'name'); - // if ($serviceName === $name) { - // $savedService->required_fqdn = true; - // $savedService->save(); - // break; - // } - // } - // } - // } else { - // if ($isDatabase) { - // $savedService = $this->databases()->whereName($serviceName)->first(); - // } else { - // $savedService = $this->applications()->whereName($serviceName)->first(); - // if (data_get($savedService, 'fqdn')) { - // $defaultUsableFqdn = data_get($savedService, 'fqdn', null); - // } else { - // $defaultUsableFqdn = $this->generateFqdn($serviceVariables, $serviceName, $configuration); - // } - // $savedService->fqdn = $defaultUsableFqdn; - // $savedService->save(); - // } - // } - - // $fqdns = data_get($savedService, 'fqdn'); - // if ($fqdns) { - // $fqdns = collect(Str::of($fqdns)->explode(',')); - // } - // // Collect ports - // $servicePorts = collect(data_get($service, 'ports', [])); - // $ports->put($serviceName, $servicePorts); - // $collectedPorts = collect([]); - // if ($servicePorts->count() > 0) { - // foreach ($servicePorts as $sport) { - // if (is_string($sport) || is_numeric($sport)) { - // $collectedPorts->push($sport); - // } - // if (is_array($sport)) { - // $target = data_get($sport, 'target'); - // $published = data_get($sport, 'published'); - // $collectedPorts->push("$target:$published"); - // } - // } - // } - // $savedService->ports = $collectedPorts->implode(','); - // $savedService->save(); - - // // Collect volumes - // $serviceVolumes = collect(data_get($service, 'volumes', [])); - // if ($serviceVolumes->count() > 0) { - // LocalPersistentVolume::whereResourceId($savedService->id)->whereResourceType(get_class($savedService))->delete(); - // foreach ($serviceVolumes as $volume) { - // if (is_string($volume)) { - // if (Str::startsWith($volume, './')) { - // $fsPath = Str::before($volume, ':'); - // $volumePath = Str::of($volume)->after(':')->beforeLast(':'); - // LocalFileVolume::updateOrCreate( - // [ - // 'mount_path' => $volumePath, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ], - // [ - // 'fs_path' => $fsPath, - // 'mount_path' => $volumePath, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ] - // ); - // $savedService->saveFileVolumes(); - // continue; - // } - // $volumeName = Str::before($volume, ':'); - // $volumePath = Str::after($volume, ':'); - // } - // if (is_array($volume)) { - // $volumeName = data_get($volume, 'source'); - // $volumePath = data_get($volume, 'target'); - // $volumeContent = data_get($volume, 'content'); - // if (Str::startsWith($volumeName, './')) { - // $payload = [ - // 'fs_path' => $volumeName, - // 'mount_path' => $volumePath, - - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ]; - // if ($volumeContent) { - // $payload['content'] = $volumeContent; - // } - // LocalFileVolume::updateOrCreate( - // [ - // 'mount_path' => $volumePath, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ], - // $payload - // ); - // if ($volumeContent) { - // $volume = data_forget($volume, 'content'); - // } - // $savedService->saveFileVolumes(); - // continue; - // } - // } - - // $volumeExists = $serviceVolumes->contains(function ($_, $key) use ($volumeName) { - // return $key == $volumeName; - // }); - // if (!$volumeExists) { - // if (Str::startsWith($volumeName, '/')) { - // $volumes->put($volumeName, $volumePath); - // LocalPersistentVolume::updateOrCreate( - // [ - // 'mount_path' => $volumePath, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ], - // [ - // 'name' => Str::slug($volumeName, '-'), - // 'mount_path' => $volumePath, - // 'host_path' => $volumeName, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ] - // ); - // } else { - // $composeVolumes->put($volumeName, null); - // LocalPersistentVolume::updateOrCreate( - // [ - // 'name' => $volumeName, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ], - // [ - // 'name' => $volumeName, - // 'mount_path' => $volumePath, - // 'host_path' => null, - // 'resource_id' => $savedService->id, - // 'resource_type' => get_class($savedService) - // ] - // ); - // } - // } - // } - // } - - // // Collect and add networks - // $serviceNetworks = collect(data_get($service, 'networks', [])); - // if ($serviceNetworks->count() > 0) { - // foreach ($serviceNetworks as $networkName => $networkDetails) { - // $networkExists = $composeNetworks->contains(function ($value, $key) use ($networkName) { - // return $value == $networkName || $key == $networkName; - // }); - // if (!$networkExists) { - // $composeNetworks->put($networkDetails, null); - // } - // } - // } - // // Add Coolify specific networks - // $definedNetworkExists = $composeNetworks->contains(function ($value, $_) use ($definedNetwork) { - // return $value == $definedNetwork; - // }); - // if (!$definedNetworkExists) { - // $composeNetworks->put($definedNetwork, [ - // 'name' => $definedNetwork, - // 'external' => false - // ]); - // } - // $networks = $serviceNetworks->toArray(); - // $networks = array_merge($networks, [$definedNetwork]); - // data_set($service, 'networks', $networks); - - - - // // Get variables from the service - // foreach ($serviceVariables as $variable) { - // $value = Str::after($variable, '='); - // // if (!Str::of($val)->contains($value)) { - // // EnvironmentVariable::updateOrCreate([ - // // 'key' => $variable, - // // 'service_id' => $this->id, - // // ], [ - // // 'value' => $val, - // // 'is_build_time' => false, - // // 'service_id' => $this->id, - // // 'is_preview' => false, - // // ]); - // // continue; - // // } - // if (!Str::startsWith($value, '$SERVICE_') && !Str::startsWith($value, '${SERVICE_') && Str::startsWith($value, '$')) { - // $value = Str::of(replaceVariables(Str::of($value))); - // $nakedName = $nakedValue = null; - // if ($value->contains(':')) { - // $nakedName = $value->before(':'); - // $nakedValue = $value->after(':'); - // } else if ($value->contains('-')) { - // $nakedName = $value->before('-'); - // $nakedValue = $value->after('-'); - // } else if ($value->contains('+')) { - // $nakedName = $value->before('+'); - // $nakedValue = $value->after('+'); - // } else { - // $nakedName = $value; - // } - // if (isset($nakedName)) { - // if (isset($nakedValue)) { - // if ($nakedValue->startsWith('-')) { - // $nakedValue = Str::of($nakedValue)->after('-'); - // } - // if ($nakedValue->startsWith('+')) { - // $nakedValue = Str::of($nakedValue)->after('+'); - // } - // if (!$envs->has($nakedName->value())) { - // $envs->put($nakedName->value(), $nakedValue->value()); - // EnvironmentVariable::updateOrCreate([ - // 'key' => $nakedName->value(), - // 'service_id' => $this->id, - // ], [ - // 'value' => $nakedValue->value(), - // 'is_build_time' => false, - // 'service_id' => $this->id, - // 'is_preview' => false, - // ]); - // } - // } else { - // if (!$envs->has($nakedName->value())) { - // $envs->put($nakedName->value(), null); - // $envExists = EnvironmentVariable::where('service_id', $this->id)->where('key', $nakedName->value())->exists(); - // if (!$envExists) { - // EnvironmentVariable::create([ - // 'key' => $nakedName->value(), - // 'value' => null, - // 'service_id' => $this->id, - // 'is_build_time' => false, - // 'is_preview' => false, - // ]); - // } - // } - // } - // } - // } else { - // $variableName = Str::of(replaceVariables(Str::of($value))); - // $generatedValue = null; - // if ($variableName->startsWith('SERVICE_USER')) { - // $variableDefined = EnvironmentVariable::whereServiceId($this->id)->where('key', $variableName->value())->first(); - // if (!$variableDefined) { - // $generatedValue = Str::random(10); - // } else { - // $generatedValue = $variableDefined->value; - // } - // if (!$envs->has($variableName->value())) { - // $envs->put($variableName->value(), $generatedValue); - // EnvironmentVariable::updateOrCreate([ - // 'key' => $variableName->value(), - // 'service_id' => $this->id, - // ], [ - // 'value' => $generatedValue, - // 'is_build_time' => false, - // 'service_id' => $this->id, - // 'is_preview' => false, - // ]); - // } - // } else if ($variableName->startsWith('SERVICE_PASSWORD')) { - // $variableDefined = EnvironmentVariable::whereServiceId($this->id)->where('key', $variableName->value())->first(); - // if (!$variableDefined) { - // if ($variableName->startsWith('SERVICE_PASSWORD64')) { - // $generatedValue = Str::password(length: 64, symbols: false); - // } else { - // $generatedValue = Str::password(symbols: false); - // } - // } else { - // $generatedValue = $variableDefined->value; - // } - // if (!$envs->has($variableName->value())) { - // $envs->put($variableName->value(), $generatedValue); - // EnvironmentVariable::updateOrCreate([ - // 'key' => $variableName->value(), - // 'service_id' => $this->id, - // ], [ - // 'value' => $generatedValue, - // 'is_build_time' => false, - // 'service_id' => $this->id, - // 'is_preview' => false, - // ]); - // } - // } else if ($variableName->startsWith('SERVICE_BASE64')) { - // $variableDefined = EnvironmentVariable::whereServiceId($this->id)->where('key', $variableName->value())->first(); - // $length = Str::of($variableName)->after('SERVICE_BASE64_')->beforeLast('_')->value(); - // if (is_numeric($length)) { - // $length = (int) $length; - // } else { - // $length = 1; - // } - // if (!$variableDefined) { - // $generatedValue = base64_encode(Str::password(length: $length, symbols: false)); - // } else { - // $generatedValue = $variableDefined->value; - // } - // if (!$envs->has($variableName->value())) { - // $envs->put($variableName->value(), $generatedValue); - // EnvironmentVariable::updateOrCreate([ - // 'key' => $variableName->value(), - // 'service_id' => $this->id, - // ], [ - // 'value' => $generatedValue, - // 'is_build_time' => false, - // 'service_id' => $this->id, - // 'is_preview' => false, - // ]); - // } - // } else if ($variableName->startsWith('SERVICE_FQDN')) { - // if ($fqdns) { - // $number = Str::of($variableName)->after('SERVICE_FQDN')->afterLast('_')->value(); - // if (is_numeric($number)) { - // $number = (int) $number - 1; - // } else { - // $number = 0; - // } - // $fqdn = getFqdnWithoutPort(data_get($fqdns, $number, $fqdns->first())); - // $environments = collect(data_get($service, 'environment')); - // $environments = $environments->map(function ($envValue) use ($value, $fqdn) { - // $envValue = Str::of($envValue)->replace($value, $fqdn); - // return $envValue->value(); - // }); - // $service['environment'] = $environments->toArray(); - // } - // } else if ($variableName->startsWith('SERVICE_URL')) { - // if ($fqdns) { - // $number = Str::of($variableName)->after('SERVICE_URL')->afterLast('_')->value(); - // if (is_numeric($number)) { - // $number = (int) $number - 1; - // } else { - // $number = 0; - // } - // $fqdn = getFqdnWithoutPort(data_get($fqdns, $number, $fqdns->first())); - // $url = Url::fromString($fqdn)->getHost(); - // $environments = collect(data_get($service, 'environment')); - // $environments = $environments->map(function ($envValue) use ($value, $url) { - // $envValue = Str::of($envValue)->replace($value, $url); - // return $envValue->value(); - // }); - // $service['environment'] = $environments->toArray(); - // } - // } - // } - // } - - // // Add labels to the service - // $labels = collect(data_get($service, 'labels', [])); - // $labels = collect([]); - // $labels = $labels->merge(defaultLabels($this->id, $container_name, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id)); - // if (!$isDatabase) { - // if ($fqdns) { - // $labels = $labels->merge(fqdnLabelsForTraefik($fqdns, $container_name, true)); - // } - // } - - - // data_set($service, 'labels', $labels->toArray()); - // data_forget($service, 'is_database'); - // data_set($service, 'restart', RESTART_MODE); - // data_set($service, 'container_name', $container_name); - // data_forget($service, 'volumes.*.content'); - // return $service; - // }); - // $finalServices = [ - // 'version' => $dockerComposeVersion, - // 'services' => $services->toArray(), - // 'volumes' => $composeVolumes->toArray(), - // 'networks' => $composeNetworks->toArray(), - // ]; - // data_forget($yaml, 'services.*.volumes.*.content'); - // $this->docker_compose_raw = Yaml::dump($yaml, 10, 2); - // $this->docker_compose = Yaml::dump($finalServices, 10, 2); - // $this->save(); - // $this->saveComposeConfigs(); - // $shouldBeDefined = collect([ - // 'envs' => $envs, - // 'volumes' => $volumes, - // 'ports' => $ports - // ]); - // $parsedCompose = collect([ - // 'dockerCompose' => $finalServices, - // 'shouldBeDefined' => $shouldBeDefined - // ]); - // return $parsedCompose; } else { return collect([]); } diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index 83980d364..f835ab753 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -40,14 +40,4 @@ public function saveFileVolumes() { saveFileVolumesHelper($this); } - public function configurationRequired() { - $required = false; - foreach($this->fileStorages as $fileStorage) { - if (!$fileStorage->is_directory && $fileStorage->content == null) { - $required = true; - break; - } - } - return $required; - } } diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index c73d641f2..09b216219 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -30,14 +30,4 @@ public function saveFileVolumes() { saveFileVolumesHelper($this); } - public function configurationRequired() { - $required = false; - foreach($this->fileStorages as $fileStorage) { - if (!$fileStorage->is_directory && $fileStorage->content == null) { - $required = true; - break; - } - } - return $required; - } } diff --git a/examples/docker-compose-postgres.yaml b/examples/docker-compose-postgres.yaml new file mode 100644 index 000000000..49e0bd44c --- /dev/null +++ b/examples/docker-compose-postgres.yaml @@ -0,0 +1,15 @@ +services: + postgres: + image: postgres + command: 'postgres -c config_file=/etc/postgresql/postgresql.conf' + volumes: + - type: bind + source: ./postgresql.conf + target: /etc/postgresql/postgresql.conf + - type: bind + source: ./docker-entrypoint-initdb.d + target: /docker-entrypoint-initdb.d/ + isDirectory: true + environment: + POSTGRES_USER: $SERVICE_USER_POSTGRES + POSTGRES_PASSWORD: $SERVICE_PASSWORD_POSTGRES diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index 843b75b0e..e38ab5f05 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -1,17 +1,12 @@ -
{{ $fileStorage->mount_path }} - @if (is_null($fileStorage->content) && !$fileStorage->is_directory) - (required) - @endif -
+
{{ $fileStorage->mount_path }}
- @if ($fileStorage->is_directory) @else diff --git a/resources/views/livewire/project/service/show.blade.php b/resources/views/livewire/project/service/show.blade.php index 3a9145711..7db827fcc 100644 --- a/resources/views/livewire/project/service/show.blade.php +++ b/resources/views/livewire/project/service/show.blade.php @@ -10,9 +10,6 @@ @click.prevent="activeTab = 'general'; window.location.hash = 'general'" href="#">General Storages - @if ($serviceApplication?->configurationRequired() || $serviceDatabase?->configurationRequired()) - (?) - @endif
diff --git a/resources/views/livewire/project/shared/storages/all.blade.php b/resources/views/livewire/project/shared/storages/all.blade.php index 32cd5d299..22215f6a9 100644 --- a/resources/views/livewire/project/shared/storages/all.blade.php +++ b/resources/views/livewire/project/shared/storages/all.blade.php @@ -22,7 +22,7 @@ @endif @empty -
No storages found.
+
No volume storages found.
@endforelse