feat: new server checking job

feat: show if the server  has problems on ui
This commit is contained in:
Andras Bacsai
2024-08-05 15:48:15 +02:00
parent bc48b42ff1
commit e4b92bb660
19 changed files with 539 additions and 383 deletions

View File

@@ -104,6 +104,8 @@ class Application extends BaseModel
protected $guarded = [];
protected $appends = ['server_status'];
protected static function booted()
{
static::saving(function ($application) {
@@ -466,6 +468,28 @@ class Application extends BaseModel
return $this->getRawOriginal('status');
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
if ($this->additional_servers->count() === 0) {
return $this->destination->server->isFunctional();
} else {
$additional_servers_status = $this->additional_servers->pluck('pivot.status');
$main_server_status = $this->destination->server->isFunctional();
foreach ($additional_servers_status as $status) {
$server_status = str($status)->before(':')->value();
if ($main_server_status !== $server_status) {
return false;
}
}
return true;
}
}
);
}
public function status(): Attribute
{
return Attribute::make(

View File

@@ -5,6 +5,7 @@ namespace App\Models;
use App\Actions\Server\InstallDocker;
use App\Enums\ProxyTypes;
use App\Jobs\PullSentinelImageJob;
use App\Notifications\Server\Revived;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Support\Collection;
@@ -677,7 +678,49 @@ $schema://$host {
return instant_remote_process(["docker start $id"], $this);
}
public function getContainers(): Collection
public function getContainers()
{
$containers = collect([]);
$containerReplicates = collect([]);
if ($this->isSwarm()) {
$containers = instant_remote_process(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this, false);
$containers = format_docker_command_output_to_json($containers);
$containerReplicates = instant_remote_process(["docker service ls --format '{{json .}}'"], $this, false);
if ($containerReplicates) {
$containerReplicates = format_docker_command_output_to_json($containerReplicates);
foreach ($containerReplicates as $containerReplica) {
$name = data_get($containerReplica, 'Name');
$containers = $containers->map(function ($container) use ($name, $containerReplica) {
if (data_get($container, 'Spec.Name') === $name) {
$replicas = data_get($containerReplica, 'Replicas');
$running = str($replicas)->explode('/')[0];
$total = str($replicas)->explode('/')[1];
if ($running === $total) {
data_set($container, 'State.Status', 'running');
data_set($container, 'State.Health.Status', 'healthy');
} else {
data_set($container, 'State.Status', 'starting');
data_set($container, 'State.Health.Status', 'unhealthy');
}
}
return $container;
});
}
}
} else {
$containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this, false);
$containers = format_docker_command_output_to_json($containers);
$containerReplicates = collect([]);
}
return [
'containers' => $containers ?? collect([]),
'containerReplicates' => $containerReplicates ?? collect([]),
];
}
public function getContainersWithSentinel(): Collection
{
$sentinel_found = instant_remote_process(['docker inspect coolify-sentinel'], $this, false);
$sentinel_found = json_decode($sentinel_found, true);
@@ -690,21 +733,6 @@ $schema://$host {
$containers = data_get(json_decode($containers, true), 'containers', []);
return collect($containers);
} else {
if ($this->isSwarm()) {
$containers = instant_remote_process(["docker service inspect $(docker service ls -q) --format '{{json .}}'"], $this, false);
} else {
$containers = instant_remote_process(['docker container ls -q'], $this, false);
if (! $containers) {
return collect([]);
}
$containers = instant_remote_process(["docker container inspect $(docker container ls -q) --format '{{json .}}'"], $this, false);
}
if (is_null($containers)) {
return collect([]);
}
return format_docker_command_output_to_json($containers);
}
}

View File

@@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
@@ -39,6 +40,8 @@ class Service extends BaseModel
protected $guarded = [];
protected $appends = ['server_status'];
public function isConfigurationChanged(bool $save = false)
{
$domains = $this->applications()->get()->pluck('fqdn')->sort()->toArray();
@@ -77,6 +80,15 @@ class Service extends BaseModel
}
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->server->isFunctional();
}
);
}
public function isRunning()
{
return (bool) str($this->status())->contains('running');

View File

@@ -14,7 +14,7 @@ class StandaloneClickhouse extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'clickhouse_password' => 'encrypted',
@@ -40,6 +40,15 @@ class StandaloneClickhouse extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings;

View File

@@ -14,7 +14,7 @@ class StandaloneDragonfly extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'dragonfly_password' => 'encrypted',
@@ -40,6 +40,15 @@ class StandaloneDragonfly extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings;

View File

@@ -14,7 +14,7 @@ class StandaloneKeydb extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url'];
protected $appends = ['internal_db_url', 'external_db_url', 'server_status'];
protected $casts = [
'keydb_password' => 'encrypted',
@@ -40,6 +40,15 @@ class StandaloneKeydb extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings.$this->keydb_conf;

View File

@@ -14,7 +14,7 @@ class StandaloneMariadb extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'mariadb_password' => 'encrypted',
@@ -40,6 +40,15 @@ class StandaloneMariadb extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings.$this->mariadb_conf;

View File

@@ -14,7 +14,7 @@ class StandaloneMongodb extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected static function booted()
{
@@ -44,6 +44,15 @@ class StandaloneMongodb extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings.$this->mongo_conf;

View File

@@ -14,7 +14,7 @@ class StandaloneMysql extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'mysql_password' => 'encrypted',
@@ -41,6 +41,15 @@ class StandaloneMysql extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings.$this->mysql_conf;

View File

@@ -14,7 +14,7 @@ class StandalonePostgresql extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected $casts = [
'init_scripts' => 'array',
@@ -46,6 +46,15 @@ class StandalonePostgresql extends BaseModel
return database_configuration_dir()."/{$this->uuid}";
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function delete_configurations()
{
$server = data_get($this, 'destination.server');

View File

@@ -14,7 +14,7 @@ class StandaloneRedis extends BaseModel
protected $guarded = [];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type'];
protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status'];
protected static function booted()
{
@@ -36,6 +36,15 @@ class StandaloneRedis extends BaseModel
});
}
protected function serverStatus(): Attribute
{
return Attribute::make(
get: function () {
return $this->destination->server->isFunctional();
}
);
}
public function isConfigurationChanged(bool $save = false)
{
$newConfigHash = $this->image.$this->ports_mappings.$this->redis_conf;