diff --git a/app/Console/Commands/Init.php b/app/Console/Commands/Init.php index 0efd9b025..e98d43013 100644 --- a/app/Console/Commands/Init.php +++ b/app/Console/Commands/Init.php @@ -6,6 +6,8 @@ use App\Models\Application; use App\Models\ApplicationDeploymentQueue; use App\Models\Service; +use App\Models\ServiceApplication; +use App\Models\StandaloneMariadb; use App\Models\StandaloneMongodb; use App\Models\StandaloneMysql; use App\Models\StandalonePostgresql; @@ -61,77 +63,129 @@ private function cleanup_stucked_resources() try { $applications = Application::all(); foreach ($applications as $application) { - if (!$application->environment) { + if (!data_get($application, 'environment')) { ray('Application without environment', $application->name); $application->delete(); } + if (!data_get($application, 'server')) { + ray('Application without server', $application->name); + $application->delete(); + } if (!$application->destination()) { ray('Application without destination', $application->name); $application->delete(); } } + } catch (\Throwable $e) { + echo "Error in application: {$e->getMessage()}\n"; + } + try { $postgresqls = StandalonePostgresql::all(); foreach ($postgresqls as $postgresql) { - if (!$postgresql->environment) { + if (!data_get($postgresql, 'environment')) { ray('Postgresql without environment', $postgresql->name); $postgresql->delete(); } + if (!data_get($postgresql, 'server')) { + ray('Postgresql without server', $postgresql->name); + $postgresql->delete(); + } if (!$postgresql->destination()) { ray('Postgresql without destination', $postgresql->name); $postgresql->delete(); } } + } catch (\Throwable $e) { + echo "Error in postgresql: {$e->getMessage()}\n"; + } + try { $redis = StandaloneRedis::all(); foreach ($redis as $redis) { - if (!$redis->environment) { + if (!data_get($redis, 'environment')) { ray('Redis without environment', $redis->name); $redis->delete(); } + if (!data_get($redis, 'server')) { + ray('Redis without server', $redis->name); + $redis->delete(); + } if (!$redis->destination()) { ray('Redis without destination', $redis->name); $redis->delete(); } } + } catch (\Throwable $e) { + echo "Error in redis: {$e->getMessage()}\n"; + } + + try { $mongodbs = StandaloneMongodb::all(); foreach ($mongodbs as $mongodb) { - if (!$mongodb->environment) { + if (!data_get($mongodb, 'environment')) { ray('Mongodb without environment', $mongodb->name); $mongodb->delete(); } + if (!data_get($mongodb, 'server')) { + ray('Mongodb without server', $mongodb->name); + $mongodb->delete(); + } if (!$mongodb->destination()) { ray('Mongodb without destination', $mongodb->name); $mongodb->delete(); } } + } catch (\Throwable $e) { + echo "Error in mongodb: {$e->getMessage()}\n"; + } + + try { $mysqls = StandaloneMysql::all(); foreach ($mysqls as $mysql) { - if (!$mysql->environment) { + if (!data_get($mysql, 'environment')) { ray('Mysql without environment', $mysql->name); $mysql->delete(); } + if (!data_get($mysql, 'server')) { + ray('Mysql without server', $mysql->name); + $mysql->delete(); + } if (!$mysql->destination()) { ray('Mysql without destination', $mysql->name); $mysql->delete(); } } - $mariadbs = StandaloneMysql::all(); + } catch (\Throwable $e) { + echo "Error in mysql: {$e->getMessage()}\n"; + } + + try { + $mariadbs = StandaloneMariadb::all(); foreach ($mariadbs as $mariadb) { - if (!$mariadb->environment) { + if (!data_get($mariadb, 'environment')) { ray('Mariadb without environment', $mariadb->name); $mariadb->delete(); } + if (!data_get($mariadb, 'server')) { + ray('Mariadb without server', $mariadb->name); + $mariadb->delete(); + } if (!$mariadb->destination()) { ray('Mariadb without destination', $mariadb->name); $mariadb->delete(); } } + } catch (\Throwable $e) { + echo "Error in mariadb: {$e->getMessage()}\n"; + } + + try { $services = Service::all(); foreach ($services as $service) { - if (!$service->environment) { + if (!data_get($service, 'environment')) { ray('Service without environment', $service->name); $service->delete(); } - if (!$service->server) { + if (!data_get($service, 'server')) { ray('Service without server', $service->name); $service->delete(); } @@ -141,7 +195,18 @@ private function cleanup_stucked_resources() } } } catch (\Throwable $e) { - echo "Error: {$e->getMessage()}\n"; + echo "Error in service: {$e->getMessage()}\n"; + } + try { + $serviceApplications = ServiceApplication::all(); + foreach ($serviceApplications as $service) { + if (!data_get($service, 'service')) { + ray('ServiceApplication without service', $service->name); + $service->delete(); + } + } + } catch (\Throwable $e) { + echo "Error in serviceApplications: {$e->getMessage()}\n"; } } } diff --git a/app/Http/Livewire/Server/Delete.php b/app/Http/Livewire/Server/Delete.php index 966de4f19..8680d4cf0 100644 --- a/app/Http/Livewire/Server/Delete.php +++ b/app/Http/Livewire/Server/Delete.php @@ -14,7 +14,7 @@ public function delete() { try { $this->authorize('delete', $this->server); - if (!$this->server->isEmpty()) { + if ($this->server->hasDefinedResources()) { $this->emit('error', 'Server has defined resources. Please delete them first.'); return; } diff --git a/app/Models/Application.php b/app/Models/Application.php index 2e6c2814d..ca7334b7e 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -34,8 +34,11 @@ protected static function booted() static::deleting(function ($application) { $application->settings()->delete(); $storages = $application->persistentStorages()->get(); - foreach ($storages as $storage) { - instant_remote_process(["docker volume rm -f $storage->name"], $application->destination->server, false); + $server = data_get($application, 'destination.server'); + if ($server) { + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); + } } $application->persistentStorages()->delete(); $application->environment_variables()->delete(); diff --git a/app/Models/Server.php b/app/Models/Server.php index 11be55764..eca98889e 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -109,11 +109,12 @@ public function scopeWithProxy(): Builder return $this->proxy->modelScope(); } - public function isEmpty() + public function hasDefinedResources() { $applications = $this->applications()->count() === 0; $databases = $this->databases()->count() === 0; - if ($applications && $databases) { + $services = $this->services()->count() === 0; + if ($applications || $databases || $services) { return true; } return false; diff --git a/app/Models/Service.php b/app/Models/Service.php index b51190887..6aaa126e7 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -5,7 +5,6 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Relations\HasMany; use Illuminate\Support\Collection; -use Illuminate\Support\Facades\Cache; use Symfony\Component\Yaml\Yaml; use Illuminate\Support\Str; @@ -23,21 +22,21 @@ protected static function booted() foreach ($storages as $storage) { $storagesToDelete->push($storage); } - $application->persistentStorages()->delete(); } foreach ($service->databases()->get() as $database) { $storages = $database->persistentStorages()->get(); foreach ($storages as $storage) { $storagesToDelete->push($storage); } - $database->persistentStorages()->delete(); } $service->environment_variables()->delete(); $service->applications()->delete(); $service->databases()->delete(); - if ($storagesToDelete->count() > 0) { - $storagesToDelete->each(function ($storage) use ($service) { - instant_remote_process(["docker volume rm -f $storage->name"], $service->server, false); + + $server = data_get($service, 'server'); + if ($server && $storagesToDelete->count() > 0) { + $storagesToDelete->each(function ($storage) use ($server) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); }); } }); diff --git a/app/Models/ServiceApplication.php b/app/Models/ServiceApplication.php index 284453c42..c70ceeccf 100644 --- a/app/Models/ServiceApplication.php +++ b/app/Models/ServiceApplication.php @@ -11,6 +11,13 @@ class ServiceApplication extends BaseModel use HasFactory; protected $guarded = []; + protected static function booted() + { + static::deleting(function ($service) { + $service->persistentStorages()->delete(); + $service->fileStorages()->delete(); + }); + } public function type() { return 'service'; diff --git a/app/Models/ServiceDatabase.php b/app/Models/ServiceDatabase.php index b4a130904..900cdc3b4 100644 --- a/app/Models/ServiceDatabase.php +++ b/app/Models/ServiceDatabase.php @@ -9,6 +9,13 @@ class ServiceDatabase extends BaseModel use HasFactory; protected $guarded = []; + protected static function booted() + { + static::deleting(function ($service) { + $service->persistentStorages()->delete(); + $service->fileStorages()->delete(); + }); + } public function type() { return 'service'; diff --git a/app/Models/StandaloneMariadb.php b/app/Models/StandaloneMariadb.php index 5e721857b..f9f3ad1ae 100644 --- a/app/Models/StandaloneMariadb.php +++ b/app/Models/StandaloneMariadb.php @@ -30,8 +30,11 @@ protected static function booted() }); static::deleting(function ($database) { $storages = $database->persistentStorages()->get(); - foreach ($storages as $storage) { - instant_remote_process(["docker volume rm -f $storage->name"], $database->destination->server, false); + $server = data_get($database, 'destination.server'); + if ($server) { + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); + } } $database->scheduledBackups()->delete(); $database->persistentStorages()->delete(); diff --git a/app/Models/StandaloneMongodb.php b/app/Models/StandaloneMongodb.php index 6e3b9e583..628cb6942 100644 --- a/app/Models/StandaloneMongodb.php +++ b/app/Models/StandaloneMongodb.php @@ -33,8 +33,11 @@ protected static function booted() }); static::deleting(function ($database) { $storages = $database->persistentStorages()->get(); - foreach ($storages as $storage) { - instant_remote_process(["docker volume rm -f $storage->name"], $database->destination->server, false); + $server = data_get($database, 'destination.server'); + if ($server) { + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); + } } $database->scheduledBackups()->delete(); $database->persistentStorages()->delete(); diff --git a/app/Models/StandaloneMysql.php b/app/Models/StandaloneMysql.php index 53a797d49..d7314f59b 100644 --- a/app/Models/StandaloneMysql.php +++ b/app/Models/StandaloneMysql.php @@ -30,8 +30,11 @@ protected static function booted() }); static::deleting(function ($database) { $storages = $database->persistentStorages()->get(); - foreach ($storages as $storage) { - instant_remote_process(["docker volume rm -f $storage->name"], $database->destination->server, false); + $server = data_get($database, 'destination.server'); + if ($server) { + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); + } } $database->scheduledBackups()->delete(); $database->persistentStorages()->delete(); diff --git a/app/Models/StandalonePostgresql.php b/app/Models/StandalonePostgresql.php index bbfabbf67..ca19e7a87 100644 --- a/app/Models/StandalonePostgresql.php +++ b/app/Models/StandalonePostgresql.php @@ -30,8 +30,11 @@ protected static function booted() }); static::deleting(function ($database) { $storages = $database->persistentStorages()->get(); - foreach ($storages as $storage) { - instant_remote_process(["docker volume rm -f $storage->name"], $database->destination->server, false); + $server = data_get($database, 'destination.server'); + if ($server) { + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); + } } $database->scheduledBackups()->delete(); $database->persistentStorages()->delete(); diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index 9dff7ae84..9d12df040 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -26,8 +26,11 @@ protected static function booted() static::deleting(function ($database) { $database->scheduledBackups()->delete(); $storages = $database->persistentStorages()->get(); - foreach ($storages as $storage) { - instant_remote_process(["docker volume rm -f $storage->name"], $database->destination->server, false); + $server = data_get($database, 'destination.server'); + if ($server) { + foreach ($storages as $storage) { + instant_remote_process(["docker volume rm -f $storage->name"], $server, false); + } } $database->persistentStorages()->delete(); $database->environment_variables()->delete(); diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index 0eb280c08..ebd0c7a82 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -60,6 +60,14 @@ services: - /var/run/docker.sock:/var/run/docker.sock - /data/coolify/:/data/coolify # - coolify-data-dev:/data/coolify + remote-host: + <<: *testing-host-base + container_name: coolify-remote-host + volumes: + - /:/host + - /var/run/docker.sock:/var/run/docker.sock + - /data/coolify/:/data/coolify + # - coolify-data-dev:/data/coolify mailpit: image: "axllent/mailpit:latest" container_name: coolify-mail diff --git a/resources/views/livewire/server/delete.blade.php b/resources/views/livewire/server/delete.blade.php index b4a9a030f..1cf2e1d74 100644 --- a/resources/views/livewire/server/delete.blade.php +++ b/resources/views/livewire/server/delete.blade.php @@ -11,8 +11,12 @@
This will remove this server from Coolify. Beware! There is no coming back!
- - Delete - + @if ($server->hasDefinedResources()) +
Please delete all resources before deleting this server.
+ @else + + Delete + + @endif @endif diff --git a/resources/views/livewire/server/form.blade.php b/resources/views/livewire/server/form.blade.php index 047bf1882..c9ed332de 100644 --- a/resources/views/livewire/server/form.blade.php +++ b/resources/views/livewire/server/form.blade.php @@ -62,7 +62,6 @@ helper="Disk cleanup job will be executed if disk usage is more than this number." /> @endif -