clearAll(); $template = Str::of($template); $network = data_get($application, 'destination.network'); $yaml = Yaml::parse($template); $services = data_get($yaml, 'services'); $volumes = collect(data_get($yaml, 'volumes', [])); $composeVolumes = collect([]); $env = collect([]); $ports = collect([]); foreach ($services as $serviceName => $service) { // Some default things data_set($service, 'restart', RESTART_MODE); data_set($service, 'container_name', generateApplicationContainerName($application)); $healthcheck = data_get($service, 'healthcheck', []); if (is_null($healthcheck)) { $healthcheck = [ 'test' => [ 'CMD-SHELL', 'exit 0' ], 'interval' => $application->health_check_interval . 's', 'timeout' => $application->health_check_timeout . 's', 'retries' => $application->health_check_retries, 'start_period' => $application->health_check_start_period . 's' ]; data_set($service, 'healthcheck', $healthcheck); } // Add volumes to the volumes collection if they don't already exist $serviceVolumes = collect(data_get($service, 'volumes', [])); if ($serviceVolumes->count() > 0) { foreach ($serviceVolumes as $volume) { $volumeName = Str::before($volume, ':'); $volumePath = Str::after($volume, ':'); if (Str::startsWith($volumeName, '/')) { continue; } $volumeExists = $volumes->contains(function ($_, $key) use ($volumeName) { return $key == $volumeName; }); if ($volumeExists) { ray('Volume already exists'); } else { $composeVolumes->put($volumeName, null); $volumes->put($volumeName, $volumePath); } } } // Add networks to the networks collection if they don't already exist $serviceNetworks = collect(data_get($service, 'networks', [])); $networkExists = $serviceNetworks->contains(function ($_, $key) use ($network) { return $key == $network; }); if (is_null($networkExists) || !$networkExists) { $serviceNetworks->push($network); } data_set($service, 'networks', $serviceNetworks->toArray()); data_set($yaml, "services.{$serviceName}", $service); // Get variables from the service that does not start with SERVICE_* $serviceVariables = collect(data_get($service, 'environment', [])); foreach ($serviceVariables as $variable) { $key = Str::before($variable, '='); $value = Str::after($variable, '='); if (!Str::startsWith($value, '$SERVICE_') && !Str::startsWith($value, '${SERVICE_') && Str::startsWith($value, '$')) { if (Str::of($value)->contains(':')) { $nakedName = replaceVariables(Str::of($value)->before(':')); $nakedValue = replaceVariables(Str::of($value)->after(':')); } if (Str::of($value)->contains('-')) { $nakedName = replaceVariables(Str::of($value)->before('-')); $nakedValue = replaceVariables(Str::of($value)->after('-')); } if (Str::of($value)->contains('+')) { $nakedName = replaceVariables(Str::of($value)->before('+')); $nakedValue = replaceVariables(Str::of($value)->after('+')); } if ($nakedValue->startsWith('-')) { $nakedValue = Str::of($nakedValue)->after('-'); } if ($nakedValue->startsWith('+')) { $nakedValue = Str::of($nakedValue)->after('+'); } if (!$env->contains("{$nakedName->value()}={$nakedValue->value()}")) { $env->push("$nakedName=$nakedValue"); } } } // Get ports from the service $servicePorts = collect(data_get($service, 'ports', [])); foreach ($servicePorts as $port) { $port = Str::of($port)->before(':'); $ports->push($port); } } data_set($yaml, 'networks', [ $network => [ 'name'=> $network ], ]); data_set($yaml, 'volumes', $composeVolumes->toArray()); $compose = Str::of(Yaml::dump($yaml, 10, 2)); // Replace SERVICE_FQDN_* with the actual FQDN preg_match_all(collectRegex('SERVICE_FQDN_'), $compose, $fqdns); $fqdns = collect($fqdns)->flatten()->unique()->values(); $generatedFqdns = collect([]); foreach ($fqdns as $fqdn) { $generatedFqdns->put("$fqdn", data_get($application, 'fqdn')); } // Replace SERVICE_URL_* preg_match_all(collectRegex('SERVICE_URL_'), $compose, $urls); $urls = collect($urls)->flatten()->unique()->values(); $generatedUrls = collect([]); foreach ($urls as $url) { $generatedUrls->put("$url", data_get($application, 'url')); } // Generate SERVICE_USER_* preg_match_all(collectRegex('SERVICE_USER_'), $compose, $users); $users = collect($users)->flatten()->unique()->values(); $generatedUsers = collect([]); foreach ($users as $user) { $generatedUsers->put("$user", Str::random(10)); } // Generate SERVICE_PASSWORD_* preg_match_all(collectRegex('SERVICE_PASSWORD_'), $compose, $passwords); $passwords = collect($passwords)->flatten()->unique()->values(); $generatedPasswords = collect([]); foreach ($passwords as $password) { $generatedPasswords->put("$password", Str::password(symbols: false)); } // Save .env file foreach ($generatedFqdns as $key => $value) { $env->push("$key=$value"); } foreach ($generatedUrls as $key => $value) { $env->push("$key=$value"); } foreach ($generatedUsers as $key => $value) { $env->push("$key=$value"); } foreach ($generatedPasswords as $key => $value) { $env->push("$key=$value"); } return [ 'dockercompose' => $compose, 'yaml' => Yaml::parse($compose), 'envs' => $env, 'volumes' => $volumes, 'ports' => $ports->values(), ]; } function replaceRegex(?string $name = null) { return "/\\\${?{$name}[^}]*}?|\\\${$name}\w+/"; } function collectRegex(string $name) { return "/{$name}\w+/"; } function replaceVariables($variable) { return $variable->replaceFirst('$', '')->replaceFirst('{', '')->replaceLast('}', ''); }