coolify/bootstrap/helpers/services.php

219 lines
10 KiB
PHP
Raw Normal View History

2023-09-19 15:51:13 +02:00
<?php
use App\Models\Application;
2023-09-27 12:45:53 +02:00
use App\Models\EnvironmentVariable;
use App\Models\ServiceApplication;
use App\Models\ServiceDatabase;
2024-02-21 12:22:32 +01:00
use Spatie\Url\Url;
2023-09-26 14:45:52 +02:00
use Symfony\Component\Yaml\Yaml;
2023-09-19 15:51:13 +02:00
function replaceRegex(?string $name = null)
{
return "/\\\${?{$name}[^}]*}?|\\\${$name}\w+/";
}
function collectRegex(string $name)
{
return "/{$name}\w+/";
}
function replaceVariables($variable)
{
return $variable->before('}')->replaceFirst('$', '')->replaceFirst('{', '');
2023-09-19 15:51:13 +02:00
}
2023-09-21 21:30:13 +02:00
function getFilesystemVolumesFromServer(ServiceApplication|ServiceDatabase|Application $oneService, bool $isInit = false)
{
try {
if ($oneService->getMorphClass() === 'App\Models\Application') {
$workdir = $oneService->workdir();
$server = $oneService->destination->server;
} else {
$workdir = $oneService->service->workdir();
$server = $oneService->service->server;
}
$fileVolumes = $oneService->fileStorages()->get();
$commands = collect([
2023-09-26 14:45:52 +02:00
"mkdir -p $workdir > /dev/null 2>&1 || true",
2024-06-10 22:43:34 +02:00
"cd $workdir",
]);
instant_remote_process($commands, $server);
foreach ($fileVolumes as $fileVolume) {
$path = str(data_get($fileVolume, 'fs_path'));
$content = data_get($fileVolume, 'content');
if ($path->startsWith('.')) {
$path = $path->after('.');
2024-06-10 22:43:34 +02:00
$fileLocation = $workdir.$path;
} else {
$fileLocation = $path;
}
// Exists and is a file
$isFile = instant_remote_process(["test -f $fileLocation && echo OK || echo NOK"], $server);
// Exists and is a directory
$isDir = instant_remote_process(["test -d $fileLocation && echo OK || echo NOK"], $server);
if ($isFile == 'OK') {
// If its a file & exists
$filesystemContent = instant_remote_process(["cat $fileLocation"], $server);
$fileVolume->content = $filesystemContent;
$fileVolume->is_directory = false;
$fileVolume->save();
2024-06-10 22:43:34 +02:00
} elseif ($isDir == 'OK') {
// If its a directory & exists
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
2024-06-10 22:43:34 +02:00
} elseif ($isFile == 'NOK' && $isDir == 'NOK' && ! $fileVolume->is_directory && $isInit && $content) {
// Does not exists (no dir or file), not flagged as directory, is init, has content
$fileVolume->content = $content;
$fileVolume->is_directory = false;
$fileVolume->save();
$content = base64_encode($content);
$dir = str($fileLocation)->dirname();
instant_remote_process([
"mkdir -p $dir",
2024-06-10 22:43:34 +02:00
"echo '$content' | base64 -d | tee $fileLocation",
], $server);
2024-06-10 22:43:34 +02:00
} elseif ($isFile == 'NOK' && $isDir == 'NOK' && $fileVolume->is_directory && $isInit) {
// Does not exists (no dir or file), flagged as directory, is init
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
instant_remote_process(["mkdir -p $fileLocation"], $server);
} elseif ($isFile == 'NOK' && $isDir == 'NOK' && ! $fileVolume->is_directory && $isInit && ! $content) {
// Does not exists (no dir or file), not flagged as directory, is init, has no content => create directory
$fileVolume->content = null;
$fileVolume->is_directory = true;
$fileVolume->save();
instant_remote_process(["mkdir -p $fileLocation"], $server);
}
}
} catch (\Throwable $e) {
return handleError($e);
}
2023-09-21 21:30:13 +02:00
}
function updateCompose(ServiceApplication|ServiceDatabase $resource)
{
2023-09-26 14:45:52 +02:00
try {
$name = data_get($resource, 'name');
$dockerComposeRaw = data_get($resource, 'service.docker_compose_raw');
if (! $dockerComposeRaw) {
throw new \Exception('No compose file found or not a valid YAML file.');
}
2023-09-26 14:45:52 +02:00
$dockerCompose = Yaml::parse($dockerComposeRaw);
2023-09-27 12:45:53 +02:00
// Switch Image
$updatedImage = data_get_str($resource, 'image');
$currentImage = data_get_str($dockerCompose, "services.{$name}.image");
if ($currentImage !== $updatedImage) {
data_set($dockerCompose, "services.{$name}.image", $updatedImage->value());
$dockerComposeRaw = Yaml::dump($dockerCompose, 10, 2);
$resource->service->docker_compose_raw = $dockerComposeRaw;
$resource->service->save();
$resource->image = $updatedImage;
$resource->save();
}
if ($resource->fqdn) {
$resourceFqdns = str($resource->fqdn)->explode(',');
if ($resourceFqdns->count() === 1) {
$resourceFqdns = $resourceFqdns->first();
$variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'LIKE', "{$variableName}_%")->first();
$fqdn = Url::fromString($resourceFqdns);
$port = $fqdn->getPort();
2024-05-22 15:45:30 +02:00
$path = $fqdn->getPath();
2024-06-10 22:43:34 +02:00
$fqdn = $fqdn->getScheme().'://'.$fqdn->getHost();
if ($generatedEnv) {
2024-06-10 22:43:34 +02:00
$generatedEnv->value = $fqdn.$path;
$generatedEnv->save();
}
if ($port) {
2024-06-10 22:43:34 +02:00
$variableName = $variableName."_$port";
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
2024-05-22 15:45:30 +02:00
// ray($generatedEnv);
if ($generatedEnv) {
2024-06-10 22:43:34 +02:00
$generatedEnv->value = $fqdn.$path;
$generatedEnv->save();
}
}
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'LIKE', "{$variableName}_%")->first();
$url = Url::fromString($fqdn);
$port = $url->getPort();
2024-05-22 15:45:30 +02:00
$path = $url->getPath();
$url = $url->getHost();
if ($generatedEnv) {
$url = str($fqdn)->after('://');
2024-06-10 22:43:34 +02:00
$generatedEnv->value = $url.$path;
$generatedEnv->save();
}
if ($port) {
2024-06-10 22:43:34 +02:00
$variableName = $variableName."_$port";
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
if ($generatedEnv) {
2024-06-10 22:43:34 +02:00
$generatedEnv->value = $url.$path;
$generatedEnv->save();
}
}
2024-06-10 22:43:34 +02:00
} elseif ($resourceFqdns->count() > 1) {
foreach ($resourceFqdns as $fqdn) {
$host = Url::fromString($fqdn);
$port = $host->getPort();
$url = $host->getHost();
2024-05-22 15:45:30 +02:00
$path = $host->getPath();
2024-06-10 22:43:34 +02:00
$host = $host->getScheme().'://'.$host->getHost();
if ($port) {
$port_envs = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'like', "SERVICE_FQDN_%_$port")->get();
foreach ($port_envs as $port_env) {
$service_fqdn = str($port_env->key)->beforeLast('_')->after('SERVICE_FQDN_');
2024-06-10 22:43:34 +02:00
$env = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'SERVICE_FQDN_'.$service_fqdn)->first();
if ($env) {
2024-06-10 22:43:34 +02:00
$env->value = $host.$path;
$env->save();
}
2024-06-10 22:43:34 +02:00
$port_env->value = $host.$path;
$port_env->save();
}
$port_envs_url = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'like', "SERVICE_URL_%_$port")->get();
foreach ($port_envs_url as $port_env_url) {
$service_url = str($port_env_url->key)->beforeLast('_')->after('SERVICE_URL_');
2024-06-10 22:43:34 +02:00
$env = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'SERVICE_URL_'.$service_url)->first();
if ($env) {
2024-06-10 22:43:34 +02:00
$env->value = $url.$path;
$env->save();
}
2024-06-10 22:43:34 +02:00
$port_env_url->value = $url.$path;
$port_env_url->save();
}
} else {
$variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$fqdn = Url::fromString($fqdn);
2024-06-10 22:43:34 +02:00
$fqdn = $fqdn->getScheme().'://'.$fqdn->getHost().$fqdn->getPath();
if ($generatedEnv) {
$generatedEnv->value = $fqdn;
$generatedEnv->save();
}
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$url = Url::fromString($fqdn);
2024-06-10 22:43:34 +02:00
$url = $url->getHost().$url->getPath();
if ($generatedEnv) {
$url = str($fqdn)->after('://');
$generatedEnv->value = $url;
$generatedEnv->save();
}
}
}
2023-11-11 21:32:41 +01:00
}
2023-10-04 14:40:26 +02:00
}
2023-09-26 14:45:52 +02:00
} catch (\Throwable $e) {
return handleError($e);
}
}
2024-07-09 13:30:13 +02:00
function serviceKeys()
{
$services = get_service_templates();
$serviceKeys = $services->keys();
return $serviceKeys;
}