feat: migrate env variables to polymorphic relationship

fix: proxy status query ui
This commit is contained in:
Andras Bacsai 2024-12-17 10:38:32 +01:00
parent 7edd2285b5
commit 2a9d499251
33 changed files with 625 additions and 374 deletions

View file

@ -27,6 +27,9 @@ private function removeSensitiveData($application)
{
$application->makeHidden([
'id',
'resourceable',
'resourceable_id',
'resourceable_type',
]);
if (request()->attributes->get('can_read_sensitive', false) === false) {
$application->makeHidden([
@ -1893,8 +1896,9 @@ public function update_env_by_uuid(Request $request)
$is_preview = $request->is_preview ?? false;
$is_build_time = $request->is_build_time ?? false;
$is_literal = $request->is_literal ?? false;
$key = str($request->key)->trim()->replace(' ', '_')->value;
if ($is_preview) {
$env = $application->environment_variables_preview->where('key', $request->key)->first();
$env = $application->environment_variables_preview->where('key', $key)->first();
if ($env) {
$env->value = $request->value;
if ($env->is_build_time != $is_build_time) {
@ -1921,7 +1925,7 @@ public function update_env_by_uuid(Request $request)
], 404);
}
} else {
$env = $application->environment_variables->where('key', $request->key)->first();
$env = $application->environment_variables->where('key', $key)->first();
if ($env) {
$env->value = $request->value;
if ($env->is_build_time != $is_build_time) {
@ -2064,6 +2068,7 @@ public function create_bulk_envs(Request $request)
$bulk_data = collect($bulk_data)->map(function ($item) {
return collect($item)->only(['key', 'value', 'is_preview', 'is_build_time', 'is_literal']);
});
$returnedEnvs = collect();
foreach ($bulk_data as $item) {
$validator = customApiValidator($item, [
'key' => 'string|required',
@ -2085,8 +2090,9 @@ public function create_bulk_envs(Request $request)
$is_literal = $item->get('is_literal') ?? false;
$is_multi_line = $item->get('is_multiline') ?? false;
$is_shown_once = $item->get('is_shown_once') ?? false;
$key = str($item->get('key'))->trim()->replace(' ', '_')->value;
if ($is_preview) {
$env = $application->environment_variables_preview->where('key', $item->get('key'))->first();
$env = $application->environment_variables_preview->where('key', $key)->first();
if ($env) {
$env->value = $item->get('value');
if ($env->is_build_time != $is_build_time) {
@ -2111,10 +2117,12 @@ public function create_bulk_envs(Request $request)
'is_literal' => $is_literal,
'is_multiline' => $is_multi_line,
'is_shown_once' => $is_shown_once,
'resourceable_type' => get_class($application),
'resourceable_id' => $application->id,
]);
}
} else {
$env = $application->environment_variables->where('key', $item->get('key'))->first();
$env = $application->environment_variables->where('key', $key)->first();
if ($env) {
$env->value = $item->get('value');
if ($env->is_build_time != $is_build_time) {
@ -2139,12 +2147,15 @@ public function create_bulk_envs(Request $request)
'is_literal' => $is_literal,
'is_multiline' => $is_multi_line,
'is_shown_once' => $is_shown_once,
'resourceable_type' => get_class($application),
'resourceable_id' => $application->id,
]);
}
}
$returnedEnvs->push($this->removeSensitiveData($env));
}
return response()->json($this->removeSensitiveData($env))->setStatusCode(201);
return response()->json($returnedEnvs)->setStatusCode(201);
}
#[OA\Post(
@ -2257,8 +2268,10 @@ public function create_env(Request $request)
], 422);
}
$is_preview = $request->is_preview ?? false;
$key = str($request->key)->trim()->replace(' ', '_')->value;
if ($is_preview) {
$env = $application->environment_variables_preview->where('key', $request->key)->first();
$env = $application->environment_variables_preview->where('key', $key)->first();
if ($env) {
return response()->json([
'message' => 'Environment variable already exists. Use PATCH request to update it.',
@ -2272,6 +2285,8 @@ public function create_env(Request $request)
'is_literal' => $request->is_literal ?? false,
'is_multiline' => $request->is_multiline ?? false,
'is_shown_once' => $request->is_shown_once ?? false,
'resourceable_type' => get_class($application),
'resourceable_id' => $application->id,
]);
return response()->json([
@ -2279,7 +2294,7 @@ public function create_env(Request $request)
])->setStatusCode(201);
}
} else {
$env = $application->environment_variables->where('key', $request->key)->first();
$env = $application->environment_variables->where('key', $key)->first();
if ($env) {
return response()->json([
'message' => 'Environment variable already exists. Use PATCH request to update it.',
@ -2293,6 +2308,8 @@ public function create_env(Request $request)
'is_literal' => $request->is_literal ?? false,
'is_multiline' => $request->is_multiline ?? false,
'is_shown_once' => $request->is_shown_once ?? false,
'resourceable_type' => get_class($application),
'resourceable_id' => $application->id,
]);
return response()->json([
@ -2380,7 +2397,10 @@ public function delete_env_by_uuid(Request $request)
'message' => 'Application not found.',
], 404);
}
$found_env = EnvironmentVariable::where('uuid', $request->env_uuid)->where('application_id', $application->id)->first();
$found_env = EnvironmentVariable::where('uuid', $request->env_uuid)
->where('resourceable_type', Application::class)
->where('resourceable_id', $application->id)
->first();
if (! $found_env) {
return response()->json([
'message' => 'Environment variable not found.',

View file

@ -20,6 +20,9 @@ private function removeSensitiveData($service)
{
$service->makeHidden([
'id',
'resourceable',
'resourceable_id',
'resourceable_type',
]);
if (request()->attributes->get('can_read_sensitive', false) === false) {
$service->makeHidden([
@ -333,7 +336,8 @@ public function create_service(Request $request)
EnvironmentVariable::create([
'key' => $key,
'value' => $generatedValue,
'service_id' => $service->id,
'resourceable_id' => $service->id,
'resourceable_type' => $service->getMorphClass(),
'is_build_time' => false,
'is_preview' => false,
]);
@ -673,7 +677,8 @@ public function update_env_by_uuid(Request $request)
], 422);
}
$env = $service->environment_variables()->where('key', $request->key)->first();
$key = str($request->key)->trim()->replace(' ', '_')->value;
$env = $service->environment_variables()->where('key', $key)->first();
if (! $env) {
return response()->json(['message' => 'Environment variable not found.'], 404);
}
@ -799,9 +804,9 @@ public function create_bulk_envs(Request $request)
'errors' => $validator->errors(),
], 422);
}
$key = str($item['key'])->trim()->replace(' ', '_')->value;
$env = $service->environment_variables()->updateOrCreate(
['key' => $item['key']],
['key' => $key],
$item
);
@ -909,7 +914,8 @@ public function create_env(Request $request)
], 422);
}
$existingEnv = $service->environment_variables()->where('key', $request->key)->first();
$key = str($request->key)->trim()->replace(' ', '_')->value;
$existingEnv = $service->environment_variables()->where('key', $key)->first();
if ($existingEnv) {
return response()->json([
'message' => 'Environment variable already exists. Use PATCH request to update it.',
@ -995,7 +1001,8 @@ public function delete_env_by_uuid(Request $request)
}
$env = EnvironmentVariable::where('uuid', $request->env_uuid)
->where('service_id', $service->id)
->where('resourceable_type', Service::class)
->where('resourceable_id', $service->id)
->first();
if (! $env) {

View file

@ -23,7 +23,7 @@ class DeploymentNavbar extends Component
public function mount()
{
$this->application = Application::find($this->application_deployment_queue->application_id);
$this->application = Application::ownedByCurrentTeam()->find($this->application_deployment_queue->application_id);
$this->server = $this->application->destination->server;
$this->is_debug_enabled = $this->application->settings->is_debug_enabled;
}

View file

@ -119,7 +119,7 @@ public function clone(string $type)
$environmentVaribles = $application->environment_variables()->get();
foreach ($environmentVaribles as $environmentVarible) {
$newEnvironmentVariable = $environmentVarible->replicate()->fill([
'application_id' => $newApplication->id,
'resourceable_id' => $newApplication->id,
]);
$newEnvironmentVariable->save();
}
@ -145,17 +145,8 @@ public function clone(string $type)
$environmentVaribles = $database->environment_variables()->get();
foreach ($environmentVaribles as $environmentVarible) {
$payload = [];
if ($database->type() === 'standalone-postgresql') {
$payload['standalone_postgresql_id'] = $newDatabase->id;
} elseif ($database->type() === 'standalone-redis') {
$payload['standalone_redis_id'] = $newDatabase->id;
} elseif ($database->type() === 'standalone-mongodb') {
$payload['standalone_mongodb_id'] = $newDatabase->id;
} elseif ($database->type() === 'standalone-mysql') {
$payload['standalone_mysql_id'] = $newDatabase->id;
} elseif ($database->type() === 'standalone-mariadb') {
$payload['standalone_mariadb_id'] = $newDatabase->id;
}
$payload['resourceable_id'] = $newDatabase->id;
$payload['resourceable_type'] = $newDatabase->getMorphClass();
$newEnvironmentVariable = $environmentVarible->replicate()->fill($payload);
$newEnvironmentVariable->save();
}

View file

@ -87,7 +87,8 @@ public function submit()
'value' => $variable,
'is_build_time' => false,
'is_preview' => false,
'service_id' => $service->id,
'resourceable_id' => $service->id,
'resourceable_type' => $service->getMorphClass(),
]);
}
$service->name = "service-$service->uuid";

View file

@ -95,7 +95,8 @@ public function mount()
EnvironmentVariable::create([
'key' => $key,
'value' => $value,
'service_id' => $service->id,
'resourceable_id' => $service->id,
'resourceable_type' => $service->getMorphClass(),
'is_build_time' => false,
'is_preview' => false,
]);

View file

@ -4,7 +4,6 @@
use App\Models\EnvironmentVariable;
use Livewire\Component;
use Visus\Cuid2\Cuid2;
class All extends Component
{
@ -14,38 +13,35 @@ class All extends Component
public bool $showPreview = false;
public ?string $modalId = null;
public ?string $variables = null;
public ?string $variablesPreview = null;
public string $view = 'normal';
public bool $is_env_sorting_enabled = false;
protected $listeners = [
'saveKey' => 'submit',
'refreshEnvs',
'environmentVariableDeleted' => 'refreshEnvs',
];
protected $rules = [
'resource.settings.is_env_sorting_enabled' => 'required|boolean',
];
public function mount()
{
$this->is_env_sorting_enabled = data_get($this->resource, 'settings.is_env_sorting_enabled', false);
$this->resourceClass = get_class($this->resource);
$resourceWithPreviews = [\App\Models\Application::class];
$simpleDockerfile = ! is_null(data_get($this->resource, 'dockerfile'));
$simpleDockerfile = filled(data_get($this->resource, 'dockerfile'));
if (str($this->resourceClass)->contains($resourceWithPreviews) && ! $simpleDockerfile) {
$this->showPreview = true;
}
$this->modalId = new Cuid2;
$this->sortEnvironmentVariables();
}
public function instantSave()
{
$this->resource->settings->is_env_sorting_enabled = $this->is_env_sorting_enabled;
$this->resource->settings->save();
$this->sortEnvironmentVariables();
$this->dispatch('success', 'Environment variable settings updated.');
@ -53,7 +49,7 @@ public function instantSave()
public function sortEnvironmentVariables()
{
if (! data_get($this->resource, 'settings.is_env_sorting_enabled')) {
if ($this->is_env_sorting_enabled === false) {
if ($this->resource->environment_variables) {
$this->resource->environment_variables = $this->resource->environment_variables->sortBy('order')->values();
}
@ -178,35 +174,12 @@ private function createEnvironmentVariable($data)
$environment->is_multiline = $data['is_multiline'] ?? false;
$environment->is_literal = $data['is_literal'] ?? false;
$environment->is_preview = $data['is_preview'] ?? false;
$resourceType = $this->resource->type();
$resourceIdField = $this->getResourceIdField($resourceType);
if ($resourceIdField) {
$environment->$resourceIdField = $this->resource->id;
}
$environment->resourceable_id = $this->resource->id;
$environment->resourceable_type = $this->resource->getMorphClass();
return $environment;
}
private function getResourceIdField($resourceType)
{
$resourceTypes = [
'application' => 'application_id',
'standalone-postgresql' => 'standalone_postgresql_id',
'standalone-redis' => 'standalone_redis_id',
'standalone-mongodb' => 'standalone_mongodb_id',
'standalone-mysql' => 'standalone_mysql_id',
'standalone-mariadb' => 'standalone_mariadb_id',
'standalone-keydb' => 'standalone_keydb_id',
'standalone-dragonfly' => 'standalone_dragonfly_id',
'standalone-clickhouse' => 'standalone_clickhouse_id',
'service' => 'service_id',
];
return $resourceTypes[$resourceType] ?? null;
}
private function deleteRemovedVariables($isPreview, $variables)
{
$method = $isPreview ? 'environment_variables_preview' : 'environment_variables';
@ -231,34 +204,14 @@ private function updateOrCreateVariables($isPreview, $variables)
$environment->is_build_time = false;
$environment->is_multiline = false;
$environment->is_preview = $isPreview;
$environment->resourceable_id = $this->resource->id;
$environment->resourceable_type = $this->resource->getMorphClass();
$this->setEnvironmentResourceId($environment);
$environment->save();
}
}
}
private function setEnvironmentResourceId($environment)
{
$resourceTypes = [
'application' => 'application_id',
'standalone-postgresql' => 'standalone_postgresql_id',
'standalone-redis' => 'standalone_redis_id',
'standalone-mongodb' => 'standalone_mongodb_id',
'standalone-mysql' => 'standalone_mysql_id',
'standalone-mariadb' => 'standalone_mariadb_id',
'standalone-keydb' => 'standalone_keydb_id',
'standalone-dragonfly' => 'standalone_dragonfly_id',
'standalone-clickhouse' => 'standalone_clickhouse_id',
'service' => 'service_id',
];
$resourceType = $this->resource->type();
if (isset($resourceTypes[$resourceType])) {
$environment->{$resourceTypes[$resourceType]} = $this->resource->id;
}
}
public function refreshEnvs()
{
$this->resource->refresh();

View file

@ -20,6 +20,26 @@ class Show extends Component
public string $type;
public string $key;
public ?string $value = null;
public ?string $real_value = null;
public bool $is_shared = false;
public bool $is_build_time = false;
public bool $is_multiline = false;
public bool $is_literal = false;
public bool $is_shown_once = false;
public bool $is_required = false;
public bool $is_really_required = false;
protected $listeners = [
'refreshEnvs' => 'refresh',
'refresh',
@ -27,39 +47,59 @@ class Show extends Component
];
protected $rules = [
'env.key' => 'required|string',
'env.value' => 'nullable',
'env.is_build_time' => 'required|boolean',
'env.is_multiline' => 'required|boolean',
'env.is_literal' => 'required|boolean',
'env.is_shown_once' => 'required|boolean',
'env.real_value' => 'nullable',
'env.is_required' => 'required|boolean',
'key' => 'required|string',
'value' => 'nullable',
'is_build_time' => 'required|boolean',
'is_multiline' => 'required|boolean',
'is_literal' => 'required|boolean',
'is_shown_once' => 'required|boolean',
'real_value' => 'nullable',
'is_required' => 'required|boolean',
];
protected $validationAttributes = [
'env.key' => 'Key',
'env.value' => 'Value',
'env.is_build_time' => 'Build Time',
'env.is_multiline' => 'Multiline',
'env.is_literal' => 'Literal',
'env.is_shown_once' => 'Shown Once',
'env.is_required' => 'Required',
];
public function refresh()
{
$this->env->refresh();
$this->checkEnvs();
}
public function mount()
{
$this->syncData();
if ($this->env->getMorphClass() === \App\Models\SharedEnvironmentVariable::class) {
$this->isSharedVariable = true;
}
$this->parameters = get_route_parameters();
$this->checkEnvs();
}
public function refresh()
{
$this->syncData();
$this->checkEnvs();
}
public function syncData(bool $toModel = false)
{
if ($toModel) {
$this->validate();
$this->env->key = $this->key;
$this->env->value = $this->value;
$this->env->is_build_time = $this->is_build_time;
$this->env->is_multiline = $this->is_multiline;
$this->env->is_literal = $this->is_literal;
$this->env->is_shown_once = $this->is_shown_once;
$this->env->is_required = $this->is_required;
$this->env->is_shared = $this->is_shared;
$this->env->save();
} else {
$this->key = $this->env->key;
$this->value = $this->env->value;
$this->is_build_time = $this->env->is_build_time ?? false;
$this->is_multiline = $this->env->is_multiline;
$this->is_literal = $this->env->is_literal;
$this->is_shown_once = $this->env->is_shown_once;
$this->is_required = $this->env->is_required ?? false;
$this->is_really_required = $this->env->is_really_required ?? false;
$this->is_shared = $this->env->is_shared ?? false;
$this->real_value = $this->env->real_value;
}
}
public function checkEnvs()
@ -103,17 +143,17 @@ public function submit()
try {
if ($this->isSharedVariable) {
$this->validate([
'env.key' => 'required|string',
'env.value' => 'nullable',
'env.is_shown_once' => 'required|boolean',
'key' => 'required|string',
'value' => 'nullable',
'is_shown_once' => 'required|boolean',
]);
} else {
$this->validate();
}
if (! $this->isSharedVariable && $this->env->is_required && str($this->env->real_value)->isEmpty()) {
if (! $this->isSharedVariable && $this->is_required && str($this->value)->isEmpty()) {
$oldValue = $this->env->getOriginal('value');
$this->env->value = $oldValue;
$this->value = $oldValue;
$this->dispatch('error', 'Required environment variable cannot be empty.');
return;
@ -122,10 +162,10 @@ public function submit()
$this->serialize();
if ($this->isSharedVariable) {
unset($this->env->is_required);
unset($this->is_required);
}
$this->env->save();
$this->syncData(true);
$this->dispatch('success', 'Environment variable updated.');
$this->dispatch('envsUpdated');
} catch (\Exception $e) {

View file

@ -60,7 +60,8 @@ public function cloneTo($destination_id)
$environmentVaribles = $this->resource->environment_variables()->get();
foreach ($environmentVaribles as $environmentVarible) {
$newEnvironmentVariable = $environmentVarible->replicate()->fill([
'application_id' => $new_resource->id,
'resourceable_id' => $new_resource->id,
'resourceable_type' => $new_resource->getMorphClass(),
]);
$newEnvironmentVariable->save();
}

View file

@ -695,46 +695,62 @@ public function main_port()
return $this->settings->is_static ? [80] : $this->ports_exposes_array;
}
public function environment_variables(): HasMany
public function environment_variables()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->orderBy('key', 'asc');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', false)
->orderBy('key', 'asc');
}
public function runtime_environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'not like', 'NIXPACKS_%');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', false)
->where('key', 'not like', 'NIXPACKS_%');
}
// Preview Deployments
public function build_environment_variables(): HasMany
public function build_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', false)
->where('is_build_time', true)
->where('key', 'not like', 'NIXPACKS_%');
}
public function nixpacks_environment_variables(): HasMany
public function nixpacks_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', false)->where('key', 'like', 'NIXPACKS_%');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', false)
->where('key', 'like', 'NIXPACKS_%');
}
public function environment_variables_preview(): HasMany
public function environment_variables_preview()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->orderBy('key', 'asc');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', true)
->orderByRaw("LOWER(key) LIKE LOWER('SERVICE%') DESC, LOWER(key) ASC");
}
public function runtime_environment_variables_preview(): HasMany
public function runtime_environment_variables_preview()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'not like', 'NIXPACKS_%');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', true)
->where('key', 'not like', 'NIXPACKS_%');
}
public function build_environment_variables_preview(): HasMany
public function build_environment_variables_preview()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('is_build_time', true)->where('key', 'not like', 'NIXPACKS_%');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', true)
->where('is_build_time', true)
->where('key', 'not like', 'NIXPACKS_%');
}
public function nixpacks_environment_variables_preview(): HasMany
public function nixpacks_environment_variables_preview()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->where('key', 'like', 'NIXPACKS_%');
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', true)
->where('key', 'like', 'NIXPACKS_%');
}
public function scheduled_tasks(): HasMany

View file

@ -14,9 +14,8 @@
properties: [
'id' => ['type' => 'integer'],
'uuid' => ['type' => 'string'],
'application_id' => ['type' => 'integer'],
'service_id' => ['type' => 'integer'],
'database_id' => ['type' => 'integer'],
'resourceable_type' => ['type' => 'string'],
'resourceable_id' => ['type' => 'integer'],
'is_build_time' => ['type' => 'boolean'],
'is_literal' => ['type' => 'boolean'],
'is_multiline' => ['type' => 'boolean'],
@ -42,6 +41,8 @@ class EnvironmentVariable extends Model
'is_multiline' => 'boolean',
'is_preview' => 'boolean',
'version' => 'string',
'resourceable_type' => 'string',
'resourceable_id' => 'integer',
];
protected $appends = ['real_value', 'is_shared', 'is_really_required'];
@ -53,18 +54,25 @@ protected static function booted()
$model->uuid = (string) new Cuid2;
}
});
static::created(function (EnvironmentVariable $environment_variable) {
if ($environment_variable->application_id && ! $environment_variable->is_preview) {
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)->where('application_id', $environment_variable->application_id)->where('is_preview', true)->first();
if ($environment_variable->resourceable_type === Application::class && ! $environment_variable->is_preview) {
$found = ModelsEnvironmentVariable::where('key', $environment_variable->key)
->where('resourceable_type', Application::class)
->where('resourceable_id', $environment_variable->resourceable_id)
->where('is_preview', true)
->first();
if (! $found) {
$application = Application::find($environment_variable->application_id);
if ($application->build_pack !== 'dockerfile') {
$application = Application::find($environment_variable->resourceable_id);
if ($application && $application->build_pack !== 'dockerfile') {
ModelsEnvironmentVariable::create([
'key' => $environment_variable->key,
'value' => $environment_variable->value,
'is_build_time' => $environment_variable->is_build_time,
'is_multiline' => $environment_variable->is_multiline ?? false,
'application_id' => $environment_variable->application_id,
'resourceable_type' => Application::class,
'resourceable_id' => $environment_variable->resourceable_id,
'is_preview' => true,
]);
}
@ -74,6 +82,7 @@ protected static function booted()
'version' => config('constants.coolify.version'),
]);
});
static::saving(function (EnvironmentVariable $environmentVariable) {
$environmentVariable->updateIsShared();
});
@ -92,43 +101,32 @@ protected function value(): Attribute
);
}
/**
* Get the parent resourceable model.
*/
public function resourceable()
{
return $this->morphTo();
}
public function resource()
{
$resource = null;
if ($this->application_id) {
$resource = Application::find($this->application_id);
} elseif ($this->service_id) {
$resource = Service::find($this->service_id);
} elseif ($this->standalone_postgresql_id) {
$resource = StandalonePostgresql::find($this->standalone_postgresql_id);
} elseif ($this->standalone_redis_id) {
$resource = StandaloneRedis::find($this->standalone_redis_id);
} elseif ($this->standalone_mongodb_id) {
$resource = StandaloneMongodb::find($this->standalone_mongodb_id);
} elseif ($this->standalone_mysql_id) {
$resource = StandaloneMysql::find($this->standalone_mysql_id);
} elseif ($this->standalone_mariadb_id) {
$resource = StandaloneMariadb::find($this->standalone_mariadb_id);
} elseif ($this->standalone_keydb_id) {
$resource = StandaloneKeydb::find($this->standalone_keydb_id);
} elseif ($this->standalone_dragonfly_id) {
$resource = StandaloneDragonfly::find($this->standalone_dragonfly_id);
} elseif ($this->standalone_clickhouse_id) {
$resource = StandaloneClickhouse::find($this->standalone_clickhouse_id);
}
return $resource;
return $this->resourceable;
}
public function realValue(): Attribute
{
$resource = $this->resource();
return Attribute::make(
get: function () use ($resource) {
$env = $this->get_real_environment_variables($this->value, $resource);
get: function () {
if (! $this->relationLoaded('resourceable')) {
$this->load('resourceable');
}
$resource = $this->resourceable;
if (! $resource) {
return null;
}
return data_get($env, 'value', $env);
return $this->get_real_environment_variables($this->value, $resource);
}
);
}
@ -164,7 +162,6 @@ private function get_real_environment_variables(?string $environment_variable =
if ($sharedEnvsFound->isEmpty()) {
return $environment_variable;
}
foreach ($sharedEnvsFound as $sharedEnv) {
$type = str($sharedEnv)->match('/(.*?)\./');
if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {

View file

@ -1120,7 +1120,8 @@ public function saveExtraFields($fields)
'key' => $key,
'value' => $value,
'is_build_time' => false,
'service_id' => $this->id,
'resourceable_id' => $this->id,
'resourceable_type' => $this->getMorphClass(),
'is_preview' => false,
]);
}
@ -1232,14 +1233,17 @@ public function scheduled_tasks(): HasMany
return $this->hasMany(ScheduledTask::class)->orderBy('name', 'asc');
}
public function environment_variables(): HasMany
public function environment_variables()
{
return $this->hasMany(EnvironmentVariable::class)->orderByRaw("LOWER(key) LIKE LOWER('SERVICE%') DESC, LOWER(key) ASC");
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
public function environment_variables_preview(): HasMany
public function environment_variables_preview()
{
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->orderByRaw("LOWER(key) LIKE LOWER('SERVICE%') DESC, LOWER(key) ASC");
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->where('is_preview', true)
->orderByRaw("LOWER(key) LIKE LOWER('SERVICE%') DESC, LOWER(key) ASC");
}
public function workdir()

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneClickhouse extends BaseModel
@ -251,14 +250,15 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
public function runtime_environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneDragonfly extends BaseModel
@ -251,14 +250,9 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
}
public function runtime_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()
@ -319,4 +313,10 @@ public function isBackupSolutionAvailable()
{
return false;
}
public function environment_variables()
{
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
}

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneKeydb extends BaseModel
@ -251,14 +250,9 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
}
public function runtime_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()
@ -319,4 +313,10 @@ public function isBackupSolutionAvailable()
{
return false;
}
public function environment_variables()
{
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
}

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneMariadb extends BaseModel
@ -251,14 +250,15 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
public function runtime_environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneMongodb extends BaseModel
@ -271,14 +270,9 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
}
public function runtime_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()
@ -339,4 +333,10 @@ public function isBackupSolutionAvailable()
{
return true;
}
public function environment_variables()
{
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
}

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneMysql extends BaseModel
@ -252,14 +251,9 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
}
public function runtime_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()
@ -320,4 +314,10 @@ public function isBackupSolutionAvailable()
{
return true;
}
public function environment_variables()
{
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
}

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandalonePostgresql extends BaseModel
@ -252,14 +251,9 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
}
public function runtime_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()
@ -320,4 +314,10 @@ public function getMemoryMetrics(int $mins = 5)
return $parsedCollection->toArray();
}
public function environment_variables()
{
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
}

View file

@ -5,7 +5,6 @@
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
class StandaloneRedis extends BaseModel
@ -262,14 +261,9 @@ public function destination()
return $this->morphTo();
}
public function environment_variables(): HasMany
public function runtime_environment_variables()
{
return $this->hasMany(EnvironmentVariable::class);
}
public function runtime_environment_variables(): HasMany
{
return $this->hasMany(EnvironmentVariable::class);
return $this->morphMany(EnvironmentVariable::class, 'resourceable');
}
public function persistentStorages()
@ -359,4 +353,10 @@ public function redisUsername(): Attribute
}
);
}
public function environment_variables()
{
return $this->morphMany(EnvironmentVariable::class, 'resourceable')
->orderBy('key', 'asc');
}
}

View file

@ -15,7 +15,8 @@ public function __construct(
public bool $disabled = false,
public bool $noStyle = false,
public ?string $modalId = null,
public string $defaultClass = 'button'
public string $defaultClass = 'button',
public bool $showLoadingIndicator = true,
) {
if ($this->noStyle) {
$this->defaultClass = '';

View file

@ -2,6 +2,7 @@
use App\Models\Application;
use App\Models\EnvironmentVariable;
use App\Models\Service;
use App\Models\ServiceApplication;
use App\Models\ServiceDatabase;
use Illuminate\Support\Stringable;
@ -119,7 +120,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
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', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$fqdn = Url::fromString($resourceFqdns);
$port = $fqdn->getPort();
$path = $fqdn->getPath();
@ -134,7 +138,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
if ($port) {
$variableName = $variableName."_$port";
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
if ($generatedEnv) {
if ($path === '/') {
$generatedEnv->value = $fqdn;
@ -145,7 +152,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
}
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$url = Url::fromString($fqdn);
$port = $url->getPort();
$path = $url->getPath();
@ -161,7 +171,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
if ($port) {
$variableName = $variableName."_$port";
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
if ($generatedEnv) {
if ($path === '/') {
$generatedEnv->value = $url;
@ -179,10 +192,16 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$path = $host->getPath();
$host = $host->getScheme().'://'.$host->getHost();
if ($port) {
$port_envs = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'like', "SERVICE_FQDN_%_$port")->get();
$port_envs = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_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_');
$env = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'SERVICE_FQDN_'.$service_fqdn)->first();
$env = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', 'SERVICE_FQDN_'.$service_fqdn)
->first();
if ($env) {
if ($path === '/') {
$env->value = $host;
@ -198,10 +217,16 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
$port_env->save();
}
$port_envs_url = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'like', "SERVICE_URL_%_$port")->get();
$port_envs_url = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_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_');
$env = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', 'SERVICE_URL_'.$service_url)->first();
$env = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', 'SERVICE_URL_'.$service_url)
->first();
if ($env) {
if ($path === '/') {
$env->value = $url;
@ -219,7 +244,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
}
} else {
$variableName = 'SERVICE_FQDN_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$fqdn = Url::fromString($fqdn);
$fqdn = $fqdn->getScheme().'://'.$fqdn->getHost().$fqdn->getPath();
if ($generatedEnv) {
@ -227,7 +255,10 @@ function updateCompose(ServiceApplication|ServiceDatabase $resource)
$generatedEnv->save();
}
$variableName = 'SERVICE_URL_'.str($resource->name)->upper()->replace('-', '');
$generatedEnv = EnvironmentVariable::where('service_id', $resource->service_id)->where('key', $variableName)->first();
$generatedEnv = EnvironmentVariable::where('resourceable_type', Service::class)
->where('resourceable_id', $resource->service_id)
->where('key', $variableName)
->first();
$url = Url::fromString($fqdn);
$url = $url->getHost().$url->getPath();
if ($generatedEnv) {

View file

@ -1819,7 +1819,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key,
'value' => $fqdn,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@ -1831,7 +1832,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$env = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
if ($env) {
$env_url = Url::fromString($savedService->fqdn);
@ -1854,14 +1856,16 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
if ($value?->startsWith('$')) {
$foundEnv = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
$value = replaceVariables($value);
$key = $value;
if ($value->startsWith('SERVICE_')) {
$foundEnv = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
['command' => $command, 'forService' => $forService, 'generatedValue' => $generatedValue, 'port' => $port] = parseEnvVariable($value);
if (! is_null($command)) {
@ -1895,7 +1899,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key,
'value' => $fqdn,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@ -1912,7 +1917,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$env = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
if ($env) {
$env_url = Url::fromString($env->value);
@ -1932,7 +1938,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'key' => $key,
'value' => $generatedValue,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@ -1957,18 +1964,21 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$foundEnv = EnvironmentVariable::where([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
])->first();
if ($foundEnv) {
$defaultValue = data_get($foundEnv, 'value');
}
EnvironmentVariable::updateOrCreate([
'key' => $key,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $defaultValue,
'is_build_time' => false,
'service_id' => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
'is_preview' => false,
]);
}
@ -2831,6 +2841,10 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
data_set($service, 'container_name', $containerName);
data_forget($service, 'volumes.*.content');
data_forget($service, 'volumes.*.isDirectory');
data_forget($service, 'volumes.*.is_directory');
data_forget($service, 'exclude_from_hc');
data_set($service, 'environment', $serviceVariables->toArray());
updateCompose($savedService);
return $service;
});
@ -2869,13 +2883,11 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if ($isApplication) {
$nameOfId = 'application_id';
$pullRequestId = $pull_request_id;
$isPullRequest = $pullRequestId == 0 ? false : true;
$server = data_get($resource, 'destination.server');
$fileStorages = $resource->fileStorages();
} elseif ($isService) {
$nameOfId = 'service_id';
$server = data_get($resource, 'server');
$allServices = get_service_templates();
} else {
@ -3042,9 +3054,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if (substr_count(str($key)->value(), '_') === 2) {
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@ -3053,9 +3066,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if (substr_count(str($key)->value(), '_') === 3) {
$newKey = str($key)->beforeLast('_');
$resource->environment_variables()->where('key', $newKey->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $newKey->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@ -3071,7 +3085,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$key = str($key);
$value = replaceVariables($value);
$command = parseCommandFromMagicEnvVariable($key);
$found = $resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->first();
$found = $resource->environment_variables()->where('key', $key->value())->where('resourceable_type', get_class($resource))->where('resourceable_id', $resource->id)->first();
if ($found) {
continue;
}
@ -3085,9 +3099,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
} elseif ($isService) {
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
}
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@ -3104,9 +3119,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$fqdn = generateFqdn($server, "$fqdnFor-$uuid");
}
$fqdn = str($fqdn)->replace('http://', '')->replace('https://', '');
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $fqdn,
'is_build_time' => false,
@ -3114,9 +3130,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
]);
} else {
$value = generateEnvValue($command, $resource);
$resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key->value(),
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@ -3464,9 +3481,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
$originalValue = $value;
$parsedValue = replaceVariables($value);
if ($value->startsWith('$SERVICE_')) {
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@ -3480,9 +3498,10 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
}
if ($key->value() === $parsedValue->value()) {
$value = null;
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,
@ -3516,22 +3535,24 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
if ($originalValue->value() === $value->value()) {
// This means the variable does not have a default value, so it needs to be created in Coolify
$parsedKeyValue = replaceVariables($value);
$resource->environment_variables()->where('key', $parsedKeyValue)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $parsedKeyValue,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'is_build_time' => false,
'is_preview' => false,
'is_required' => $isRequired,
]);
// Add the variable to the environment so it will be shown in the deployable compose file
$environment[$parsedKeyValue->value()] = $resource->environment_variables()->where('key', $parsedKeyValue)->where($nameOfId, $resource->id)->first()->value;
$environment[$parsedKeyValue->value()] = $resource->environment_variables()->where('key', $parsedKeyValue)->where('resourceable_type', get_class($resource))->where('resourceable_id', $resource->id)->first()->value;
continue;
}
$resource->environment_variables()->where('key', $key)->where($nameOfId, $resource->id)->firstOrCreate([
$resource->environment_variables()->firstOrCreate([
'key' => $key,
$nameOfId => $resource->id,
'resourceable_type' => get_class($resource),
'resourceable_id' => $resource->id,
], [
'value' => $value,
'is_build_time' => false,

View file

@ -0,0 +1,165 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('environment_variables', function (Blueprint $table) {
$table->string('resourceable_type')->nullable();
$table->unsignedBigInteger('resourceable_id')->nullable();
$table->index(['resourceable_type', 'resourceable_id']);
});
// Populate the new columns
DB::table('environment_variables')->whereNotNull('application_id')
->update([
'resourceable_type' => 'App\\Models\\Application',
'resourceable_id' => DB::raw('application_id'),
]);
DB::table('environment_variables')->whereNotNull('service_id')
->update([
'resourceable_type' => 'App\\Models\\Service',
'resourceable_id' => DB::raw('service_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_postgresql_id')
->update([
'resourceable_type' => 'App\\Models\\StandalonePostgresql',
'resourceable_id' => DB::raw('standalone_postgresql_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_redis_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneRedis',
'resourceable_id' => DB::raw('standalone_redis_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_mongodb_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneMongodb',
'resourceable_id' => DB::raw('standalone_mongodb_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_mysql_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneMysql',
'resourceable_id' => DB::raw('standalone_mysql_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_mariadb_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneMariadb',
'resourceable_id' => DB::raw('standalone_mariadb_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_keydb_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneKeydb',
'resourceable_id' => DB::raw('standalone_keydb_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_dragonfly_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneDragonfly',
'resourceable_id' => DB::raw('standalone_dragonfly_id'),
]);
DB::table('environment_variables')->whereNotNull('standalone_clickhouse_id')
->update([
'resourceable_type' => 'App\\Models\\StandaloneClickhouse',
'resourceable_id' => DB::raw('standalone_clickhouse_id'),
]);
// After successful migration, we can drop the old foreign key columns
Schema::table('environment_variables', function (Blueprint $table) {
$table->dropColumn([
'application_id',
'service_id',
'standalone_postgresql_id',
'standalone_redis_id',
'standalone_mongodb_id',
'standalone_mysql_id',
'standalone_mariadb_id',
'standalone_keydb_id',
'standalone_dragonfly_id',
'standalone_clickhouse_id',
]);
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('environment_variables', function (Blueprint $table) {
// Restore the old columns
$table->unsignedBigInteger('application_id')->nullable();
$table->unsignedBigInteger('service_id')->nullable();
$table->unsignedBigInteger('standalone_postgresql_id')->nullable();
$table->unsignedBigInteger('standalone_redis_id')->nullable();
$table->unsignedBigInteger('standalone_mongodb_id')->nullable();
$table->unsignedBigInteger('standalone_mysql_id')->nullable();
$table->unsignedBigInteger('standalone_mariadb_id')->nullable();
$table->unsignedBigInteger('standalone_keydb_id')->nullable();
$table->unsignedBigInteger('standalone_dragonfly_id')->nullable();
$table->unsignedBigInteger('standalone_clickhouse_id')->nullable();
});
Schema::table('environment_variables', function (Blueprint $table) {
// Restore data from polymorphic relationship
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\Application')
->update(['application_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\Service')
->update(['service_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandalonePostgresql')
->update(['standalone_postgresql_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneRedis')
->update(['standalone_redis_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneMongodb')
->update(['standalone_mongodb_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneMysql')
->update(['standalone_mysql_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneMariadb')
->update(['standalone_mariadb_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneKeydb')
->update(['standalone_keydb_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneDragonfly')
->update(['standalone_dragonfly_id' => DB::raw('resourceable_id')]);
DB::table('environment_variables')
->where('resourceable_type', 'App\\Models\\StandaloneClickhouse')
->update(['standalone_clickhouse_id' => DB::raw('resourceable_id')]);
// Drop the polymorphic columns
$table->dropIndex(['resourceable_type', 'resourceable_id']);
$table->dropColumn(['resourceable_type', 'resourceable_id']);
});
}
};

View file

@ -8,11 +8,13 @@
@endisset>
{{ $slot }}
@if ($attributes->whereStartsWith('wire:click')->first())
<x-loading-on-button wire:target="{{ $attributes->whereStartsWith('wire:click')->first() }}"
wire:loading.delay />
@elseif($attributes->whereStartsWith('wire:target')->first())
<x-loading-on-button wire:target="{{ $attributes->whereStartsWith('wire:target')->first() }}"
wire:loading.delay />
@if ($showLoadingIndicator)
@if ($attributes->whereStartsWith('wire:click')->first())
<x-loading-on-button wire:target="{{ $attributes->whereStartsWith('wire:click')->first() }}"
wire:loading.delay />
@elseif($attributes->whereStartsWith('wire:target')->first())
<x-loading-on-button wire:target="{{ $attributes->whereStartsWith('wire:target')->first() }}"
wire:loading.delay />
@endif
@endif
</button>

View file

@ -3,8 +3,8 @@
@if (isset($text))
<div>{{ $text }}</div>
@endif
<svg class="w-4 h-4 mx-1 ml-3 text-coollabs dark:text-warning animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24">
<svg class="w-4 h-4 mx-1 ml-3 text-coollabs dark:text-warning animate-spin" xmlns="http://www.w3.org/2000/svg"
fill="none" viewBox="0 0 24 24">
<circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle>
<path class="opacity-75" fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z">

View file

@ -49,5 +49,6 @@
<div class="order-first sm:order-last">
<livewire:server.proxy.deploy :server="$server" />
</div>
</div>
</div>

View file

@ -5,30 +5,42 @@
'noLoading' => false,
])
<div class="flex items-center">
@if (!$noLoading)
<x-loading wire:loading.delay.longer />
@endif
<span wire:loading.remove.delay.longer class="flex items-center">
<div class="badge badge-success "></div>
<div class="pl-2 pr-1 text-xs font-bold tracking-wider text-success" @if($title) title="{{$title}}" @endif>
@if ($lastDeploymentLink)
<a href="{{ $lastDeploymentLink }}" target="_blank" class="underline cursor-pointer">
{{ str($status)->before(':')->headline() }}
</a>
@else
{{ str($status)->before(':')->headline() }}
@endif
</div>
@if (!str($status)->startsWith('Proxy') && !str($status)->contains('('))
@if (str($status)->contains('unhealthy'))
<x-helper helper="Unhealthy state. <span class='dark:text-warning text-coollabs'>This doesn't mean that the resource is malfunctioning.</span><br><br>- If the resource is accessible, it indicates that no health check is configured - it is not mandatory.<br>- If the resource is not accessible (returning 404 or 503), it may indicate that a health check is needed and has not passed. <span class='dark:text-warning text-coollabs'>Your action is required.</span><br><br>More details in the <a href='https://coolify.io/docs/knowledge-base/traefik/healthcheck/' class='underline dark:text-warning text-coollabs' target='_blank'>documentation</a>." >
<div class="flex items-center">
<span wire:loading.delay.longer>
<div class="badge badge-warning"></div>
</span>
<span wire:loading.remove.delay.longer>
<div class="badge badge-success"></div>
</span>
<div class="pl-2 pr-1 text-xs font-bold tracking-wider text-success"
@if ($title) title="{{ $title }}" @endif>
@if ($lastDeploymentLink)
<a href="{{ $lastDeploymentLink }}" target="_blank" class="underline cursor-pointer">
{{ str($status)->before(':')->headline() }}
</a>
@else
{{ str($status)->before(':')->headline() }}
@endif
</div>
@php
$showUnhealthyHelper =
!str($status)->startsWith('Proxy') &&
!str($status)->contains('(') &&
str($status)->contains('unhealthy');
@endphp
@if ($showUnhealthyHelper)
<x-helper
helper="Unhealthy state. <span class='dark:text-warning text-coollabs'>This doesn't mean that the resource is malfunctioning.</span><br><br>- If the resource is accessible, it indicates that no health check is configured - it is not mandatory.<br>- If the resource is not accessible (returning 404 or 503), it may indicate that a health check is needed and has not passed. <span class='dark:text-warning text-coollabs'>Your action is required.</span><br><br>More details in the <a href='https://coolify.io/docs/knowledge-base/traefik/healthcheck/' class='underline dark:text-warning text-coollabs' target='_blank'>documentation</a>.">
<x-slot:icon>
<svg class="hidden w-4 h-4 dark:text-warning lg:block" viewBox="0 0 256 256" xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor" d="M240.26 186.1L152.81 34.23a28.74 28.74 0 0 0-49.62 0L15.74 186.1a27.45 27.45 0 0 0 0 27.71A28.31 28.31 0 0 0 40.55 228h174.9a28.31 28.31 0 0 0 24.79-14.19a27.45 27.45 0 0 0 .02-27.71m-20.8 15.7a4.46 4.46 0 0 1-4 2.2H40.55a4.46 4.46 0 0 1-4-2.2a3.56 3.56 0 0 1 0-3.73L124 46.2a4.77 4.77 0 0 1 8 0l87.44 151.87a3.56 3.56 0 0 1 .02 3.73M116 136v-32a12 12 0 0 1 24 0v32a12 12 0 0 1-24 0m28 40a16 16 0 1 1-16-16a16 16 0 0 1 16 16"></path>
<svg class="hidden w-4 h-4 dark:text-warning lg:block" viewBox="0 0 256 256"
xmlns="http://www.w3.org/2000/svg">
<path fill="currentColor"
d="M240.26 186.1L152.81 34.23a28.74 28.74 0 0 0-49.62 0L15.74 186.1a27.45 27.45 0 0 0 0 27.71A28.31 28.31 0 0 0 40.55 228h174.9a28.31 28.31 0 0 0 24.79-14.19a27.45 27.45 0 0 0 .02-27.71m-20.8 15.7a4.46 4.46 0 0 1-4 2.2H40.55a4.46 4.46 0 0 1-4-2.2a3.56 3.56 0 0 1 0-3.73L124 46.2a4.77 4.77 0 0 1 8 0l87.44 151.87a3.56 3.56 0 0 1 .02 3.73M116 136v-32a12 12 0 0 1 24 0v32a12 12 0 0 1-24 0m28 40a16 16 0 1 1-16-16a16 16 0 0 1 16 16">
</path>
</svg>
</x-slot:icon>
</x-helper>
@endif
@endif
</span>
</div>
</div>

View file

@ -3,7 +3,7 @@
<x-slide-over @startdatabase.window="slideOverOpen = true" closeWithX fullScreen>
<x-slot:title>Database Startup</x-slot:title>
<x-slot:content>
<livewire:activity-monitor header="Logs" showWaiting />
<livewire:activity-monitor header="Logs" showWaiting fullHeight />
</x-slot:content>
</x-slide-over>
<div class="navbar-main">

View file

@ -13,7 +13,7 @@
<div>Environment variables (secrets) for this resource. </div>
@if ($this->resourceClass === 'App\Models\Application' && data_get($this->resource, 'build_pack') !== 'dockercompose')
<div class="w-64 pt-2">
<x-forms.checkbox id="resource.settings.is_env_sorting_enabled" label="Sort alphabetically"
<x-forms.checkbox id="is_env_sorting_enabled" label="Sort alphabetically"
helper="Turn this off if one environment is dependent on an other. It will be sorted by creation order (like you pasted them or in the order you created them)."
instantSave></x-forms.checkbox>
</div>
@ -55,10 +55,10 @@
<h3>Preview Deployments Environment Variables</h3>
<div>Environment (secrets) variables for Preview Deployments.</div>
</div>
@foreach ($resource->environment_variables_preview as $env)
{{-- @foreach ($resource->environment_variables_preview as $env)
<livewire:project.shared.environment-variable.show wire:key="environment-{{ $env->id }}"
:env="$env" :type="$resource->type()" />
@endforeach
@endforeach --}}
@endif
@else
<form wire:submit.prevent='submit' class="flex flex-col gap-2">

View file

@ -1,17 +1,14 @@
<div>
<form wire:submit='submit'
@class([
'flex flex-col items-center gap-4 p-4 bg-white border lg:items-start dark:bg-base',
'border-error' => $env->is_really_required,
'dark:border-coolgray-300' => !$env->is_really_required,
])
>
<form wire:submit='submit' @class([
'flex flex-col items-center gap-4 p-4 bg-white border lg:items-start dark:bg-base',
'border-error' => $is_really_required,
'dark:border-coolgray-300' => !$is_really_required,
])>
@if ($isLocked)
<div class="flex flex-1 w-full gap-2">
<x-forms.input disabled id="env.key" />
<x-forms.input disabled id="key" />
<svg class="icon" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
stroke-width="2">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M5 13a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2v6a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2v-6z" />
<path d="M11 16a1 1 0 1 0 2 0a1 1 0 0 0-2 0m-3-5V7a4 4 0 1 1 8 0v4" />
</g>
@ -25,49 +22,49 @@
@else
@if ($isDisabled)
<div class="flex flex-col w-full gap-2 lg:flex-row">
<x-forms.input disabled id="env.key" />
<x-forms.input disabled type="password" id="env.value" />
@if ($env->is_shared)
<x-forms.input disabled type="password" id="env.real_value" />
<x-forms.input disabled id="key" />
<x-forms.input disabled type="password" id="value" />
@if ($is_shared)
<x-forms.input disabled type="password" id="real_value" />
@endif
</div>
@else
<div class="flex flex-col w-full gap-2 lg:flex-row">
@if ($env->is_multiline)
<x-forms.input isMultiline="{{ $env->is_multiline }}" id="env.key" />
<x-forms.textarea type="password" id="env.value" />
@if ($is_multiline)
<x-forms.input isMultiline="{{ $is_multiline }}" id="key" />
<x-forms.textarea type="password" id="value" />
@else
<x-forms.input id="env.key" />
<x-forms.input type="password" id="env.value" />
<x-forms.input id="key" />
<x-forms.input type="password" id="value" />
@endif
@if ($env->is_shared)
<x-forms.input disabled type="password" id="env.real_value" />
@if ($is_shared)
<x-forms.input disabled type="password" id="real_value" />
@endif
</div>
@endif
<div class="flex flex-col w-full gap-2 lg:flex-row">
@if ($type === 'service')
<x-forms.checkbox instantSave id="env.is_build_time"
<x-forms.checkbox instantSave id="is_build_time"
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
label="Build Variable?" />
@else
@if ($env->is_shared)
<x-forms.checkbox instantSave id="env.is_build_time"
@if ($is_shared)
<x-forms.checkbox instantSave id="is_build_time"
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
label="Build Variable?" />
<x-forms.checkbox instantSave id="env.is_literal"
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@else
@if ($isSharedVariable)
<x-forms.checkbox instantSave id="env.is_multiline" label="Is Multiline?" />
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@else
<x-forms.checkbox instantSave id="env.is_build_time"
<x-forms.checkbox instantSave id="is_build_time"
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for dockerfile, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
label="Build Variable?" />
<x-forms.checkbox instantSave id="env.is_multiline" label="Is Multiline?" />
@if (!data_get($env, 'is_multiline'))
<x-forms.checkbox instantSave id="env.is_literal"
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
@if ($is_multiline === false)
<x-forms.checkbox instantSave id="is_literal"
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
label="Is Literal?" />
@endif
@ -84,7 +81,7 @@
</x-forms.button>
<x-modal-confirmation title="Confirm Environment Variable Deletion?" isErrorButton
buttonTitle="Delete" submitAction="delete" :actions="['The selected environment variable will be permanently deleted.']"
confirmationText="{{ $env->key }}"
confirmationText="{{ $key }}"
confirmationLabel="Please confirm the execution of the actions by entering the Environment Variable Name below"
shortConfirmationLabel="Environment Variable Name" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" />
@ -97,7 +94,7 @@
</x-forms.button>
<x-modal-confirmation title="Confirm Environment Variable Deletion?" isErrorButton
buttonTitle="Delete" submitAction="delete" :actions="['The selected environment variable will be permanently deleted.']"
confirmationText="{{ $env->key }}"
confirmationText="{{ $key }}"
confirmationLabel="Please confirm the execution of the actions by entering the Environment Variable Name below"
shortConfirmationLabel="Environment Variable Name" :confirmWithPassword="false"
step2ButtonText="Permanently Delete" />

View file

@ -20,17 +20,12 @@
</a>
</button>
@endif
<x-modal-confirmation
title="Confirm Proxy Restart?"
buttonTitle="Restart Proxy"
submitAction="restart"
:actions="['This proxy will be stopped and started again.', 'All resources hosted on coolify will be unavailable during the restart.']"
:confirmWithText="false"
:confirmWithPassword="false"
step2ButtonText="Restart Proxy"
:dispatchEvent="true"
dispatchEventType="restartEvent"
>
<x-modal-confirmation title="Confirm Proxy Restart?" buttonTitle="Restart Proxy" submitAction="restart"
:actions="[
'This proxy will be stopped and started again.',
'All resources hosted on coolify will be unavailable during the restart.',
]" :confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Restart Proxy"
:dispatchEvent="true" dispatchEventType="restartEvent">
<x-slot:button-title>
<svg class="w-5 h-5 dark:text-warning" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
<g fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round"
@ -42,17 +37,12 @@
Restart Proxy
</x-slot:button-title>
</x-modal-confirmation>
<x-modal-confirmation
title="Confirm Proxy Stopping?"
buttonTitle="Stop Proxy"
submitAction="stop(true)"
:actions="['The coolify proxy will be stopped.', 'All resources hosted on coolify will be unavailable.']"
:confirmWithText="false"
:confirmWithPassword="false"
step2ButtonText="Stop Proxy"
:dispatchEvent="true"
dispatchEventType="stopEvent"
>
<x-modal-confirmation title="Confirm Proxy Stopping?" buttonTitle="Stop Proxy" submitAction="stop(true)"
:actions="[
'The coolify proxy will be stopped.',
'All resources hosted on coolify will be unavailable.',
]" :confirmWithText="false" :confirmWithPassword="false" step2ButtonText="Stop Proxy" :dispatchEvent="true"
dispatchEventType="stopEvent">
<x-slot:button-title>
<svg xmlns="http://www.w3.org/2000/svg" class="w-5 h-5 text-error" viewBox="0 0 24 24"
stroke-width="2" stroke="currentColor" fill="none" stroke-linecap="round"
@ -82,7 +72,6 @@
@script
<script>
$wire.$on('checkProxyEvent', () => {
$wire.$dispatch('info', 'Starting proxy.');
$wire.$call('checkProxy');
});
$wire.$on('restartEvent', () => {

View file

@ -1,14 +1,15 @@
<div x-init="$wire.checkProxy()" class="flex gap-2">
<x-forms.button wire:click='checkProxy(true)' :showLoadingIndicator="false">Refresh</x-forms.button>
@if (data_get($server, 'proxy.status') === 'running')
<x-status.running status="Proxy Running" noLoading />
<x-status.running status="Proxy Running" />
@elseif (data_get($server, 'proxy.status') === 'restarting')
<x-status.restarting status="Proxy Restarting" noLoading />
<x-status.restarting status="Proxy Restarting" />
@elseif (data_get($server, 'proxy.force_stop'))
<x-status.stopped status="Proxy Stopped" noLoading />
<x-status.stopped status="Proxy Stopped" />
@elseif (data_get($server, 'proxy.status') === 'exited')
<x-status.stopped status="Proxy Exited" noLoading />
<x-status.stopped status="Proxy Exited" />
@else
<x-status.stopped status="Proxy Not Running" noLoading />
<x-status.stopped status="Proxy Not Running" />
@endif
<x-forms.button wire:click='checkProxy(true)'>Refresh</x-forms.button>
</div>