wip: services
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Enums\ProxyTypes;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Relations\HasMany;
|
||||
@@ -13,10 +14,6 @@ class Service extends BaseModel
|
||||
{
|
||||
use HasFactory;
|
||||
protected $guarded = [];
|
||||
public function destination()
|
||||
{
|
||||
return $this->morphTo();
|
||||
}
|
||||
public function persistentStorages()
|
||||
{
|
||||
return $this->morphMany(LocalPersistentVolume::class, 'resource');
|
||||
@@ -46,26 +43,49 @@ class Service extends BaseModel
|
||||
{
|
||||
return $this->hasMany(ServiceDatabase::class);
|
||||
}
|
||||
public function environment()
|
||||
{
|
||||
return $this->belongsTo(Environment::class);
|
||||
}
|
||||
public function server() {
|
||||
return $this->belongsTo(Server::class);
|
||||
}
|
||||
|
||||
public function byName(string $name)
|
||||
{
|
||||
$app = $this->applications()->whereName($name)->first();
|
||||
if ($app) {
|
||||
return $app;
|
||||
}
|
||||
$db = $this->databases()->whereName($name)->first();
|
||||
if ($db) {
|
||||
return $db;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
public function environment_variables(): HasMany
|
||||
{
|
||||
return $this->hasMany(EnvironmentVariable::class)->orderBy('key', 'asc');
|
||||
}
|
||||
public function parse(bool $saveIt = false): Collection
|
||||
public function parse(bool $isNew = false): Collection
|
||||
{
|
||||
// ray()->clearAll();
|
||||
ray('Service parse');
|
||||
if ($this->docker_compose_raw) {
|
||||
ray()->clearAll();
|
||||
$yaml = Yaml::parse($this->docker_compose_raw);
|
||||
|
||||
$composeVolumes = collect(data_get($yaml, 'volumes', []));
|
||||
$composeNetworks = collect(data_get($yaml, 'networks', []));
|
||||
$dockerComposeVersion = data_get($yaml, 'version') ?? '3.8';
|
||||
$services = data_get($yaml, 'services');
|
||||
$definedNetwork = data_get($this, 'destination.network');
|
||||
$definedNetwork = $this->uuid;
|
||||
|
||||
$volumes = collect([]);
|
||||
$envs = collect([]);
|
||||
$ports = collect([]);
|
||||
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($composeVolumes, $composeNetworks, $definedNetwork, $envs, $volumes, $ports, $saveIt) {
|
||||
$services = collect($services)->map(function ($service, $serviceName) use ($composeVolumes, $composeNetworks, $definedNetwork, $envs, $volumes, $ports, $isNew) {
|
||||
$container_name = "$serviceName-{$this->uuid}";
|
||||
$isDatabase = false;
|
||||
// Decide if the service is a database
|
||||
$image = data_get($service, 'image');
|
||||
@@ -76,24 +96,49 @@ class Service extends BaseModel
|
||||
data_set($service, 'is_database', true);
|
||||
}
|
||||
}
|
||||
if ($saveIt) {
|
||||
if ($isNew) {
|
||||
if ($isDatabase) {
|
||||
$savedService = ServiceDatabase::create([
|
||||
'name' => $serviceName,
|
||||
'service_id' => $this->id
|
||||
]);
|
||||
} else {
|
||||
$defaultUsableFqdn = "http://$serviceName-{$this->uuid}.{$this->server->ip}.sslip.io";
|
||||
if (isDev()) {
|
||||
$defaultUsableFqdn = "http://$serviceName-{$this->uuid}.127.0.0.1.sslip.io";
|
||||
}
|
||||
$savedService = ServiceApplication::create([
|
||||
'name' => $serviceName,
|
||||
'fqdn' => $defaultUsableFqdn,
|
||||
'service_id' => $this->id
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
if ($isDatabase) {
|
||||
$savedService = $this->databases()->whereName($serviceName)->first();
|
||||
} else {
|
||||
$savedService = $this->applications()->whereName($serviceName)->first();
|
||||
}
|
||||
}
|
||||
$fqdn = data_get($savedService, 'fqdn');
|
||||
// Collect ports
|
||||
$servicePorts = collect(data_get($service, 'ports', []));
|
||||
$ports->put($serviceName, $servicePorts);
|
||||
if ($saveIt) {
|
||||
$savedService->ports_exposes = $servicePorts->implode(',');
|
||||
if ($isNew) {
|
||||
$ports = collect([]);
|
||||
if ($servicePorts->count() > 0) {
|
||||
foreach ($servicePorts as $sport) {
|
||||
if (is_string($sport)) {
|
||||
$ports->push($sport);
|
||||
}
|
||||
if (is_array($sport)) {
|
||||
$target = data_get($sport, 'target');
|
||||
$published = data_get($sport, 'published');
|
||||
$ports->push("$target:$published");
|
||||
}
|
||||
}
|
||||
}
|
||||
$savedService->ports_exposes = $ports->implode(',');
|
||||
$savedService->save();
|
||||
}
|
||||
// Collect volumes
|
||||
@@ -117,7 +162,7 @@ class Service extends BaseModel
|
||||
$composeVolumes->put($volumeName, null);
|
||||
}
|
||||
$volumes->put($volumeName, $volumePath);
|
||||
if ($saveIt) {
|
||||
if ($isNew) {
|
||||
LocalPersistentVolume::create([
|
||||
'name' => $volumeName,
|
||||
'mount_path' => $volumePath,
|
||||
@@ -137,7 +182,7 @@ class Service extends BaseModel
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (!$networkExists) {
|
||||
$composeNetworks->put($networkName, null);
|
||||
$composeNetworks->put($networkDetails, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -147,11 +192,16 @@ class Service extends BaseModel
|
||||
});
|
||||
if (!$definedNetworkExists) {
|
||||
$composeNetworks->put($definedNetwork, [
|
||||
'external' => true
|
||||
'name' => $definedNetwork,
|
||||
'external' => false
|
||||
]);
|
||||
}
|
||||
$networks = $serviceNetworks->toArray();
|
||||
$networks = array_merge($networks, [$definedNetwork]);
|
||||
data_set($service, 'networks', $networks);
|
||||
|
||||
// Get variables from the service that does not start with SERVICE_*
|
||||
|
||||
// Get variables from the service
|
||||
$serviceVariables = collect(data_get($service, 'environment', []));
|
||||
foreach ($serviceVariables as $variable) {
|
||||
$value = Str::after($variable, '=');
|
||||
@@ -179,7 +229,7 @@ class Service extends BaseModel
|
||||
}
|
||||
if (!$envs->has($nakedName->value())) {
|
||||
$envs->put($nakedName->value(), $nakedValue->value());
|
||||
if ($saveIt) {
|
||||
if ($isNew) {
|
||||
EnvironmentVariable::create([
|
||||
'key' => $nakedName->value(),
|
||||
'value' => $nakedValue->value(),
|
||||
@@ -192,7 +242,7 @@ class Service extends BaseModel
|
||||
} else {
|
||||
if (!$envs->has($nakedName->value())) {
|
||||
$envs->put($nakedName->value(), null);
|
||||
if ($saveIt) {
|
||||
if ($isNew) {
|
||||
EnvironmentVariable::create([
|
||||
'key' => $nakedName->value(),
|
||||
'value' => null,
|
||||
@@ -205,15 +255,15 @@ class Service extends BaseModel
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$value = Str::of(replaceVariables(Str::of($value)));
|
||||
$variableName = Str::of(replaceVariables(Str::of($value)));
|
||||
$generatedValue = null;
|
||||
if ($value->startsWith('SERVICE_USER')) {
|
||||
if ($variableName->startsWith('SERVICE_USER')) {
|
||||
$generatedValue = Str::random(10);
|
||||
if ($saveIt) {
|
||||
if (!$envs->has($value->value())) {
|
||||
$envs->put($value->value(), $generatedValue);
|
||||
if ($isNew) {
|
||||
if (!$envs->has($variableName->value())) {
|
||||
$envs->put($variableName->value(), $generatedValue);
|
||||
EnvironmentVariable::create([
|
||||
'key' => $value->value(),
|
||||
'key' => $variableName->value(),
|
||||
'value' => $generatedValue,
|
||||
'is_build_time' => false,
|
||||
'service_id' => $this->id,
|
||||
@@ -221,13 +271,13 @@ class Service extends BaseModel
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else if ($value->startsWith('SERVICE_PASSWORD')) {
|
||||
} else if ($variableName->startsWith('SERVICE_PASSWORD')) {
|
||||
$generatedValue = Str::password(symbols: false);
|
||||
if ($saveIt) {
|
||||
if (!$envs->has($value->value())) {
|
||||
$envs->put($value->value(), $generatedValue);
|
||||
if ($isNew) {
|
||||
if (!$envs->has($variableName->value())) {
|
||||
$envs->put($variableName->value(), $generatedValue);
|
||||
EnvironmentVariable::create([
|
||||
'key' => $value->value(),
|
||||
'key' => $variableName->value(),
|
||||
'value' => $generatedValue,
|
||||
'is_build_time' => false,
|
||||
'service_id' => $this->id,
|
||||
@@ -235,28 +285,74 @@ class Service extends BaseModel
|
||||
]);
|
||||
}
|
||||
}
|
||||
} else if ($variableName->startsWith('SERVICE_FQDN')) {
|
||||
if ($fqdn) {
|
||||
$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 ($fqdn) {
|
||||
$url = Str::of($fqdn)->after('https://')->before('/');
|
||||
$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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($this->server->proxyType() === ProxyTypes::TRAEFIK_V2->value) {
|
||||
$labels = collect(data_get($service, 'labels', []));
|
||||
$labels = collect([]);
|
||||
$labels = $labels->merge(defaultLabels($this->id, $container_name, type: 'service'));
|
||||
if (!$isDatabase) {
|
||||
if ($fqdn) {
|
||||
$labels = $labels->merge(fqdnLabelsForTraefik($fqdn, $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, 'documentation');
|
||||
return $service;
|
||||
});
|
||||
data_set($services, 'volumes', $composeVolumes->toArray());
|
||||
data_set($services, 'networks', $composeNetworks->toArray());
|
||||
$this->docker_compose = Yaml::parse($services);
|
||||
// $compose = Str::of(Yaml::dump($services, 10, 2));
|
||||
// TODO: Replace SERVICE_FQDN_* with the actual FQDN
|
||||
// TODO: Replace SERVICE_URL_*
|
||||
// $services = $services->map(function ($service, $serviceName) {
|
||||
// $dependsOn = collect(data_get($service, 'depends_on', []));
|
||||
// $dependsOn = $dependsOn->map(function ($value) {
|
||||
// return "$value-{$this->uuid}";
|
||||
// });
|
||||
// data_set($service, 'depends_on', $dependsOn->toArray());
|
||||
// return $service;
|
||||
// });
|
||||
// $renamedServices = collect([]);
|
||||
// collect($services)->map(function ($service, $serviceName) use ($renamedServices) {
|
||||
// $newServiceName = "$serviceName-$this->uuid";
|
||||
// $renamedServices->put($newServiceName, $service);
|
||||
// });
|
||||
|
||||
$finalServices = [
|
||||
'version' => $dockerComposeVersion,
|
||||
'services' => $services->toArray(),
|
||||
'volumes' => $composeVolumes->toArray(),
|
||||
'networks' => $composeNetworks->toArray(),
|
||||
];
|
||||
$this->docker_compose = Yaml::dump($finalServices, 10, 2);
|
||||
$this->save();
|
||||
$shouldBeDefined = collect([
|
||||
'envs' => $envs,
|
||||
'volumes' => $volumes,
|
||||
'ports' => $ports
|
||||
]);
|
||||
$parsedCompose = collect([
|
||||
'dockerCompose' => $services,
|
||||
'dockerCompose' => $finalServices,
|
||||
'shouldBeDefined' => $shouldBeDefined
|
||||
]);
|
||||
return $parsedCompose;
|
||||
|
||||
Reference in New Issue
Block a user