diff --git a/app/Actions/Service/StartService.php b/app/Actions/Service/StartService.php
index 4ca2b7114..61f6f3731 100644
--- a/app/Actions/Service/StartService.php
+++ b/app/Actions/Service/StartService.php
@@ -17,7 +17,7 @@ class StartService
$commands[] = "echo '####### Pulling images.'";
$commands[] = "docker compose pull";
$commands[] = "echo '####### Starting containers.'";
- $commands[] = "docker compose up -d";
+ $commands[] = "docker compose up -d --remove-orphans";
$commands[] = "docker network connect $service->uuid coolify-proxy 2>/dev/null || true";
$activity = remote_process($commands, $service->server);
return $activity;
diff --git a/app/Http/Livewire/Project/New/DockerCompose.php b/app/Http/Livewire/Project/New/DockerCompose.php
index a43fd0c66..ae3a1c08c 100644
--- a/app/Http/Livewire/Project/New/DockerCompose.php
+++ b/app/Http/Livewire/Project/New/DockerCompose.php
@@ -22,18 +22,82 @@ class DockerCompose extends Component
$this->query = request()->query();
if (isDev()) {
$this->dockerComposeRaw = 'services:
- plausible_events_db:
- image: clickhouse/clickhouse-server:23.3.7.5-alpine
- restart: always
- volumes:
- - event-data:/var/lib/clickhouse
- - ./clickhouse/clickhouse-config.xml:/etc/clickhouse-server/config.d/logging.xml:ro
- - ./clickhouse/clickhouse-user-config.xml:/etc/clickhouse-server/users.d/logging.xml:ro
- ulimits:
- nofile:
- soft: 262144
- hard: 262144
-';
+ ghost:
+ image: ghost:5
+ volumes:
+ - ~/configs:/etc/configs/:ro
+ - ./var/lib/ghost/content:/tmp/ghost2/content:ro
+ - /var/lib/ghost/content:/tmp/ghost/content:rw
+ - ghost-content-data:/var/lib/ghost/content
+ - type: volume
+ source: mydata
+ target: /data
+ volume:
+ nocopy: true
+ - type: bind
+ source: ./var/lib/ghost/data
+ target: /data
+ - type: bind
+ source: /tmp
+ target: /tmp
+ labels:
+ - "test.label=true"
+ ports:
+ - "3000"
+ - "3000-3005"
+ - "8000:8000"
+ - "9090-9091:8080-8081"
+ - "49100:22"
+ - "127.0.0.1:8001:8001"
+ - "127.0.0.1:5000-5010:5000-5010"
+ - "127.0.0.1::5000"
+ - "6060:6060/udp"
+ - "12400-12500:1240"
+ - target: 80
+ published: 8080
+ protocol: tcp
+ mode: host
+ networks:
+ - some-network
+ - other-network
+ environment:
+ - database__client=${DATABASE_CLIENT:-mysql}
+ - database__connection__database=${MYSQL_DATABASE:-ghost}
+ - database__connection__host=${DATABASE_CONNECTION_HOST:-mysql}
+ - test=${TEST:?true}
+ - url=$SERVICE_FQDN_GHOST
+ - database__connection__user=$SERVICE_USER_MYSQL
+ - database__connection__password=$SERVICE_PASSWORD_MYSQL
+ depends_on:
+ - mysql
+ mysql:
+ image: mysql:8.0
+ volumes:
+ - ghost-mysql-data:/var/lib/mysql
+ environment:
+ - MYSQL_USER=${SERVICE_USER_MYSQL}
+ - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL}
+ - MYSQL_DATABASE=$MYSQL_DATABASE
+ - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT}
+ - SESSION_SECRET
+ minio:
+ image: minio/minio
+ environment:
+ RACK_ENV: development
+ A: $A
+ SHOW: ${SHOW}
+ SHOW1: ${SHOW2-show1}
+ SHOW2: ${SHOW3:-show2}
+ SHOW3: ${SHOW4?show3}
+ SHOW4: ${SHOW5:?show4}
+ SHOW5: ${SERVICE_USER_MINIO}
+ SHOW6: ${SERVICE_PASSWORD_MINIO}
+ SHOW7: ${SERVICE_PASSWORD_64_MINIO}
+ SHOW8: ${SERVICE_BASE64_64_MINIO}
+ SHOW9: ${SERVICE_BASE64_128_MINIO}
+ SHOW10: ${SERVICE_BASE64_MINIO}
+ SHOW11:
+ ';
}
}
public function submit()
diff --git a/app/Http/Livewire/Project/Service/Application.php b/app/Http/Livewire/Project/Service/Application.php
index cf464b442..701a90c19 100644
--- a/app/Http/Livewire/Project/Service/Application.php
+++ b/app/Http/Livewire/Project/Service/Application.php
@@ -3,15 +3,12 @@
namespace App\Http\Livewire\Project\Service;
use App\Models\ServiceApplication;
-use Illuminate\Support\Collection;
use Livewire\Component;
class Application extends Component
{
public ServiceApplication $application;
public $parameters;
- public $fileStorages;
- protected $listeners = ["refreshFileStorages"];
protected $rules = [
'application.human_name' => 'nullable',
'application.description' => 'nullable',
@@ -28,10 +25,7 @@ class Application extends Component
{
$this->submit();
}
- public function refreshFileStorages()
- {
- $this->fileStorages = $this->application->fileStorages()->get();
- }
+
public function delete()
{
try {
@@ -45,18 +39,16 @@ class Application extends Component
public function mount()
{
$this->parameters = get_route_parameters();
- $this->fileStorages = collect();
- $this->refreshFileStorages();
}
public function submit()
{
try {
$this->validate();
$this->application->save();
- switchImage($this->application);
+ updateCompose($this->application);
$this->emit('success', 'Application saved successfully.');
} catch (\Throwable $e) {
- ray($e);
+ return handleError($e, $this);
} finally {
$this->emit('generateDockerCompose');
}
diff --git a/app/Http/Livewire/Project/Service/Database.php b/app/Http/Livewire/Project/Service/Database.php
index 0a1b13dbc..e7eab5a3a 100644
--- a/app/Http/Livewire/Project/Service/Database.php
+++ b/app/Http/Livewire/Project/Service/Database.php
@@ -35,7 +35,7 @@ class Database extends Component
try {
$this->validate();
$this->database->save();
- switchImage($this->database);
+ updateCompose($this->database);
$this->emit('success', 'Database saved successfully.');
} catch (\Throwable $e) {
ray($e);
diff --git a/app/Http/Livewire/Project/Service/FileStorage.php b/app/Http/Livewire/Project/Service/FileStorage.php
index 9e80b663b..39e250f66 100644
--- a/app/Http/Livewire/Project/Service/FileStorage.php
+++ b/app/Http/Livewire/Project/Service/FileStorage.php
@@ -20,13 +20,17 @@ class FileStorage extends Component
'fileStorage.mount_path' => 'required',
'fileStorage.content' => 'nullable',
];
- public function mount() {
+ public function mount()
+ {
$this->service = $this->fileStorage->service;
$this->fs_path = Str::of($this->fileStorage->fs_path)->beforeLast('/');
$file = Str::of($this->fileStorage->fs_path)->afterLast('/');
if (Str::of($this->fs_path)->startsWith('.')) {
$this->fs_path = Str::of($this->fs_path)->after('.');
- $this->fs_path = $this->service->service->workdir() . $this->fs_path . "/" .$file;
+ $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()
@@ -40,7 +44,8 @@ class FileStorage extends Component
return handleError($e, $this);
}
}
- public function instantSave() {
+ public function instantSave()
+ {
$this->submit();
}
public function render()
diff --git a/app/Http/Livewire/Project/Service/Index.php b/app/Http/Livewire/Project/Service/Index.php
index 827175bb2..0d44632c7 100644
--- a/app/Http/Livewire/Project/Service/Index.php
+++ b/app/Http/Livewire/Project/Service/Index.php
@@ -34,19 +34,11 @@ class Index extends Component
{
$this->applications = $this->service->applications->sort();
$this->applications->each(function ($application) {
- $application->fileStorages()->get()->each(function ($fileStorage) use ($application) {
- if (!$fileStorage->is_directory && $fileStorage->content == null) {
- $application->hasMissingFiles = true;
- }
- });
+ $application->configuration_required = $application->configurationRequired();
});
$this->databases = $this->service->databases->sort();
$this->databases->each(function ($database) {
- $database->fileStorages()->get()->each(function ($fileStorage) use ($database) {
- if (!$fileStorage->is_directory && $fileStorage->content == null) {
- $database->hasMissingFiles = true;
- }
- });
+ $database->configuration_required = $database->configurationRequired();
});
$this->emit('success', 'Stack refreshed successfully.');
}
@@ -61,24 +53,29 @@ class Index extends Component
{
return view('livewire.project.service.index');
}
- public function save()
- {
- try {
- $this->service->save();
- $this->service->parse();
- $this->service->refresh();
- $this->emit('refreshEnvs');
- $this->emit('success', 'Service saved successfully.');
- $this->service->saveComposeConfigs();
- } catch (\Throwable $e) {
- return handleError($e, $this);
- }
- }
+ // public function save()
+ // {
+ // try {
+ // $this->service->save();
+ // $this->service->parse();
+ // $this->service->refresh();
+ // $this->emit('refreshEnvs');
+ // $this->emit('success', 'Service saved successfully.');
+ // $this->service->saveComposeConfigs();
+ // } catch (\Throwable $e) {
+ // return handleError($e, $this);
+ // }
+ // }
public function submit()
{
try {
$this->validate();
$this->service->save();
+ $this->service->parse();
+ $this->service->refresh();
+ $this->service->saveComposeConfigs();
+ $this->refreshStack();
+ $this->emit('refreshEnvs');
$this->emit('success', 'Service saved successfully.');
} catch (\Throwable $e) {
return handleError($e, $this);
diff --git a/app/Models/Service.php b/app/Models/Service.php
index b820b4f2d..554ab3464 100644
--- a/app/Models/Service.php
+++ b/app/Models/Service.php
@@ -139,11 +139,9 @@ class Service extends BaseModel
}
return $defaultUsableFqdn ?? null;
}
- public function parse(bool $isNew = false, ?Collection $configuration = null): Collection
+ public function parse(bool $isNew = false): Collection
{
- if (!$configuration) {
- $configuration = collect([]);
- }
+ ray()->clearAll();
if ($this->docker_compose_raw) {
try {
$yaml = Yaml::parse($this->docker_compose_raw);
@@ -151,20 +149,160 @@ class Service extends BaseModel
throw new \Exception($e->getMessage());
}
- $composeVolumes = collect(data_get($yaml, 'volumes', []));
- $composeNetworks = collect(data_get($yaml, 'networks', []));
+ $topLevelVolumes = collect(data_get($yaml, 'volumes', []));
+ $topLevelNetworks = collect(data_get($yaml, 'networks', []));
$dockerComposeVersion = data_get($yaml, 'version') ?? '3.8';
$services = data_get($yaml, 'services');
$definedNetwork = $this->uuid;
- $volumes = collect([]);
- $envs = collect([]);
- $ports = collect([]);
-
- $services = collect($services)->map(function ($service, $serviceName) use ($composeVolumes, $composeNetworks, $definedNetwork, $envs, $volumes, $ports, $isNew, $configuration) {
- $container_name = "$serviceName-{$this->uuid}";
- $isDatabase = false;
+ $services = collect($services)->map(function ($service, $serviceName) use ($topLevelVolumes, $topLevelNetworks, $definedNetwork, $isNew) {
+ $serviceVolumes = collect(data_get($service, 'volumes', []));
+ $servicePorts = collect(data_get($service, 'ports', []));
+ $serviceNetworks = collect(data_get($service, 'networks', []));
$serviceVariables = collect(data_get($service, 'environment', []));
+ $serviceLabels = collect(data_get($service, 'labels', []));
+
+ $containerName = "$serviceName-{$this->uuid}";
+
+ // Decide if the service is a database
+ $isDatabase = false;
+ $image = data_get_str($service, 'image');
+ if ($image->contains(':')) {
+ $image = Str::of($image);
+ } else {
+ $image = Str::of($image)->append(':latest');
+ }
+ $imageName = $image->before(':');
+
+ if (collect(DATABASE_DOCKER_IMAGES)->contains($imageName)) {
+ $isDatabase = true;
+ }
+ data_set($service, 'is_database', $isDatabase);
+
+ // Create new serviceApplication or serviceDatabase
+ if ($isDatabase) {
+ if ($isNew) {
+ $savedService = ServiceDatabase::create([
+ 'name' => $serviceName,
+ 'image' => $image,
+ 'service_id' => $this->id
+ ]);
+ } else {
+ $savedService = ServiceDatabase::where([
+ 'name' => $serviceName,
+ 'service_id' => $this->id
+ ])->first();
+ }
+ } else {
+ if ($isNew) {
+ $savedService = ServiceApplication::create([
+ 'name' => $serviceName,
+ 'image' => $image,
+ 'service_id' => $this->id
+ ]);
+ } else {
+ $savedService = ServiceApplication::where([
+ 'name' => $serviceName,
+ 'service_id' => $this->id
+ ])->first();
+ }
+ }
+
+ // Collect/create/update networks
+ if ($serviceNetworks->count() > 0) {
+ foreach ($serviceNetworks as $networkName => $networkDetails) {
+ $networkExists = $topLevelNetworks->contains(function ($value, $key) use ($networkName) {
+ return $value == $networkName || $key == $networkName;
+ });
+ if (!$networkExists) {
+ $topLevelNetworks->put($networkDetails, null);
+ }
+ }
+ }
+
+ // Collect/create/update ports
+ $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');
+ $protocol = data_get($sport, 'protocol');
+ $collectedPorts->push("$target:$published/$protocol");
+ }
+ }
+ }
+ $savedService->ports = $collectedPorts->implode(',');
+ $savedService->save();
+
+ // Add Coolify specific networks
+ $definedNetworkExists = $topLevelNetworks->contains(function ($value, $_) use ($definedNetwork) {
+ return $value == $definedNetwork;
+ });
+ if (!$definedNetworkExists) {
+ $topLevelNetworks->put($definedNetwork, [
+ 'name' => $definedNetwork,
+ 'external' => false
+ ]);
+ }
+ $networks = $serviceNetworks->toArray();
+ $networks = array_merge($networks, [$definedNetwork]);
+ data_set($service, 'networks', $networks);
+
+ // Collect/create/update volumes
+ if ($serviceVolumes->count() > 0) {
+ foreach ($serviceVolumes as $volume) {
+ $type = null;
+ $source = null;
+ $target = null;
+ if (is_string($volume)) {
+ $source = Str::of($volume)->before(':');
+ $target = Str::of($volume)->after(':')->beforeLast(':');
+ if ($source->startsWith('./') || $source->startsWith('/') || $source->startsWith('~')) {
+ $type = Str::of('bind');
+ } else {
+ $type = Str::of('volume');
+ }
+ } else if (is_array($volume)) {
+ $type = data_get_str($volume, 'type');
+ $source = data_get_str($volume, 'source');
+ $target = data_get_str($volume, 'target');
+ }
+ if ($type->value() === 'bind') {
+ LocalFileVolume::updateOrCreate(
+ [
+ 'mount_path' => $target,
+ 'resource_id' => $savedService->id,
+ 'resource_type' => get_class($savedService)
+ ],
+ [
+ 'fs_path' => $source,
+ 'mount_path' => $target,
+ 'resource_id' => $savedService->id,
+ 'resource_type' => get_class($savedService)
+ ]
+ );
+ } else if ($type->value() === 'volume') {
+ $topLevelVolumes->put($source->value(), null);
+ LocalPersistentVolume::updateOrCreate(
+ [
+ 'mount_path' => $target,
+ 'resource_id' => $savedService->id,
+ 'resource_type' => get_class($savedService)
+ ],
+ [
+ 'name' => Str::slug($source, '-'),
+ 'mount_path' => $target,
+ 'resource_id' => $savedService->id,
+ 'resource_type' => get_class($savedService)
+ ]
+ );
+ }
+ }
+ }
// Add env_file with at least .env to the service
$envFile = collect(data_get($service, 'env_file', []));
@@ -177,430 +315,588 @@ class Service extends BaseModel
}
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('+');
+ foreach ($serviceVariables as $variableName => $variable) {
+ if (is_numeric($variableName)) {
+ $variable = Str::of($variable);
+ if ($variable->contains('=')) {
+ // - SESSION_SECRET=123
+ // - SESSION_SECRET=
+ $key = $variable->before('=');
+ $value = $variable->after('=');
} else {
- $nakedName = $value;
+ // - SESSION_SECRET
+ $key = $variable;
+ $value = null;
}
- 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(),
+ } else {
+ // SESSION_SECRET: 123
+ // SESSION_SECRET:
+ $key = $variableName;
+ $value = Str::of($variable);
+ }
+ if ($value?->startsWith('$')) {
+ $value = Str::of(replaceVariables($value));
+ $key = $value;
+ $foundEnv = EnvironmentVariable::where([
+ 'key' => $key,
+ 'service_id' => $this->id,
+ ])->first();
+ if ($value->startsWith('SERVICE_')) {
+ $command = $value->after('SERVICE_')->beforeLast('_');
+ $forService = $value->afterLast('_');
+ $generatedValue = null;
+ if ($command->value() === 'FQDN' || $command->value() === 'URL') {
+ $sslip = $this->sslip($this->server);
+ $fqdn = "http://$containerName.$sslip";
+ if ($foundEnv) {
+ $fqdn = data_get($foundEnv, 'value');
+ } else {
+ EnvironmentVariable::create([
+ 'key' => $key,
+ 'value' => $fqdn,
'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);
+
+ if (!$isDatabase) {
+ $savedService->fqdn = $fqdn;
+ $savedService->save();
}
} 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;
+ switch ($command) {
+ case 'PASSWORD':
+ $generatedValue = Str::password(symbols: false);
+ break;
+ case 'PASSWORD_64':
+ $generatedValue = Str::password(length: 64, symbols: false);
+ break;
+ case 'BASE64_64':
+ $generatedValue = Str::random(64);
+ break;
+ case 'BASE64_128':
+ $generatedValue = Str::random(128);
+ break;
+ case 'BASE64':
+ $generatedValue = Str::random(32);
+ break;
+ case 'USER':
+ $generatedValue = Str::random(16);
+ break;
}
- $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;
+
+ if (!$foundEnv) {
+ EnvironmentVariable::create([
+ 'key' => $key,
+ 'value' => $generatedValue,
+ 'is_build_time' => false,
+ 'service_id' => $this->id,
+ 'is_preview' => false,
+ ]);
}
- $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();
}
+ } else {
+ if ($value->contains(':-')) {
+ $key = $value->before(':');
+ $defaultValue = $value->after(':-');
+ } else if ($value->contains('-')) {
+ $key = $value->before('-');
+ $defaultValue = $value->after('-');
+ } else if ($value->contains(':?')) {
+ $key = $value->before(':');
+ $defaultValue = $value->after(':?');
+ } else if ($value->contains('?')) {
+ $key = $value->before('?');
+ $defaultValue = $value->after('?');
+ } else {
+ $key = $value;
+ $defaultValue = null;
+ }
+ EnvironmentVariable::updateOrCreate([
+ 'key' => $key,
+ 'service_id' => $this->id,
+ ], [
+ 'value' => $defaultValue,
+ 'is_build_time' => false,
+ 'service_id' => $this->id,
+ 'is_preview' => false,
+ ]);
}
}
}
// 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) {
+ $fqdns = collect(data_get($savedService, 'fqdn'));
+ $defaultLabels = defaultLabels($this->id, $containerName, type: 'service', subType: $isDatabase ? 'database' : 'application', subId: $savedService->id);
+ $serviceLabels = $serviceLabels->merge($defaultLabels);
+ if (!$isDatabase && $fqdns->count() > 0) {
if ($fqdns) {
- $labels = $labels->merge(fqdnLabelsForTraefik($fqdns, $container_name, true));
+ $serviceLabels = $serviceLabels->merge(fqdnLabelsForTraefik($fqdns, $containerName, true));
}
}
-
- data_set($service, 'labels', $labels->toArray());
+ data_set($service, 'labels', $serviceLabels->toArray());
data_forget($service, 'is_database');
data_set($service, 'restart', RESTART_MODE);
- data_set($service, 'container_name', $container_name);
+ data_set($service, 'container_name', $containerName);
data_forget($service, 'volumes.*.content');
return $service;
});
$finalServices = [
'version' => $dockerComposeVersion,
'services' => $services->toArray(),
- 'volumes' => $composeVolumes->toArray(),
- 'networks' => $composeNetworks->toArray(),
+ '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();
- $shouldBeDefined = collect([
- 'envs' => $envs,
- 'volumes' => $volumes,
- 'ports' => $ports
- ]);
- $parsedCompose = collect([
- 'dockerCompose' => $finalServices,
- 'shouldBeDefined' => $shouldBeDefined
- ]);
- return $parsedCompose;
+ 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 91bfc7d78..125c6e51d 100644
--- a/app/Models/ServiceApplication.php
+++ b/app/Models/ServiceApplication.php
@@ -30,4 +30,14 @@ class ServiceApplication extends BaseModel
{
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 09b216219..c73d641f2 100644
--- a/app/Models/ServiceDatabase.php
+++ b/app/Models/ServiceDatabase.php
@@ -30,4 +30,14 @@ class ServiceDatabase extends BaseModel
{
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/bootstrap/helpers/services.php b/bootstrap/helpers/services.php
index 830c17b39..4e6450cab 100644
--- a/bootstrap/helpers/services.php
+++ b/bootstrap/helpers/services.php
@@ -1,5 +1,6 @@
name)->upper();
+ $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
+ if ($generatedEnv){
+ $generatedEnv->value = $resource->fqdn;
+ $generatedEnv->save();
+ }
+
+ // // Update URL
+ // $variableName = "SERVICE_URL_" . Str::of($resource->name)->upper();
+ // $generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
+ // if ($generatedEnv){
+ // $generatedEnv->value = $resource->url;
+ // $generatedEnv->save();
+ // }
+
$dockerComposeRaw = Yaml::dump($dockerCompose, 10, 2);
$resource->service->docker_compose_raw = $dockerComposeRaw;
$resource->service->save();
diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php
index 803ff7062..a1610cb2f 100644
--- a/bootstrap/helpers/shared.php
+++ b/bootstrap/helpers/shared.php
@@ -11,11 +11,13 @@ use DanHarrin\LivewireRateLimiting\Exceptions\TooManyRequestsException;
use Illuminate\Database\QueryException;
use Illuminate\Mail\Message;
use Illuminate\Notifications\Messages\MailMessage;
+use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Route;
use Illuminate\Support\Str;
+use Illuminate\Support\Stringable;
use Nubs\RandomNameGenerator\All;
use Poliander\Cron\CronExpression;
use Visus\Cuid2\Cuid2;
@@ -385,3 +387,9 @@ function parseEnvFormatToArray($env_file_contents)
}
return $env_array;
}
+
+function data_get_str($data, $key, $default = null): Stringable
+{
+ $str = data_get($data, $key, $default) ?? $default;
+ return Str::of($str);
+}
diff --git a/examples/docker-compose-weird.yaml b/examples/docker-compose-weird.yaml
new file mode 100644
index 000000000..961007a9f
--- /dev/null
+++ b/examples/docker-compose-weird.yaml
@@ -0,0 +1,76 @@
+services:
+ ghost:
+ image: ghost:5
+ volumes:
+ - ~/configs:/etc/configs/:ro
+ - ./var/lib/ghost/content:/tmp/ghost2/content:ro
+ - /var/lib/ghost/content:/tmp/ghost/content:rw
+ - ghost-content-data:/var/lib/ghost/content
+ - type: volume
+ source: mydata
+ target: /data
+ volume:
+ nocopy: true
+ - type: bind
+ source: ./var/lib/ghost/data
+ target: /data
+ - type: bind
+ source: /tmp
+ target: /tmp
+ labels:
+ - "test.label=true"
+ ports:
+ - "3000"
+ - "3000-3005"
+ - "8000:8000"
+ - "9090-9091:8080-8081"
+ - "49100:22"
+ - "127.0.0.1:8001:8001"
+ - "127.0.0.1:5000-5010:5000-5010"
+ - "127.0.0.1::5000"
+ - "6060:6060/udp"
+ - "12400-12500:1240"
+ - target: 80
+ published: 8080
+ protocol: tcp
+ mode: host
+ networks:
+ - some-network
+ - other-network
+ environment:
+ - database__client=${DATABASE_CLIENT:-mysql}
+ - database__connection__database=${MYSQL_DATABASE:-ghost}
+ - database__connection__host=${DATABASE_CONNECTION_HOST:-mysql}
+ - test=${TEST:?true}
+ - url=$SERVICE_FQDN_GHOST
+ - database__connection__user=$SERVICE_USER_MYSQL
+ - database__connection__password=$SERVICE_PASSWORD_MYSQL
+ depends_on:
+ - mysql
+ mysql:
+ image: mysql:8.0
+ volumes:
+ - ghost-mysql-data:/var/lib/mysql
+ environment:
+ - MYSQL_USER=${SERVICE_USER_MYSQL}
+ - MYSQL_PASSWORD=${SERVICE_PASSWORD_MYSQL}
+ - MYSQL_DATABASE=$MYSQL_DATABASE
+ - MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQLROOT}
+ - SESSION_SECRET
+ minio:
+ image: minio/minio
+ environment:
+ RACK_ENV: development
+ A: $A
+ SHOW: ${SHOW}
+ SHOW1: ${SHOW2-show1}
+ SHOW2: ${SHOW3:-show2}
+ SHOW3: ${SHOW4?show3}
+ SHOW4: ${SHOW5:?show4}
+ SHOW5: ${SERVICE_USER_MINIO}
+ SHOW6: ${SERVICE_PASSWORD_MINIO}
+ SHOW7: ${SERVICE_PASSWORD_64_MINIO}
+ SHOW8: ${SERVICE_BASE64_64_MINIO}
+ SHOW9: ${SERVICE_BASE64_128_MINIO}
+ SHOW10: ${SERVICE_BASE64_MINIO}
+ SHOW11:
diff --git a/resources/views/livewire/project/new/docker-compose.blade.php b/resources/views/livewire/project/new/docker-compose.blade.php
index 2ec301b6b..404ef4498 100644
--- a/resources/views/livewire/project/new/docker-compose.blade.php
+++ b/resources/views/livewire/project/new/docker-compose.blade.php
@@ -44,6 +44,6 @@
- MYSQL_DATABASE=${MYSQL_DATABASE}
- MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_MYSQL_ROOT}
'>
-