server updates (#202)

* server updates

* add last update check
This commit is contained in:
Saeed Vaziry
2024-05-11 10:09:46 +02:00
committed by GitHub
parent bbe3ca802d
commit fe331fd2b3
16 changed files with 229 additions and 10 deletions

View File

@ -2,6 +2,7 @@
namespace App\Actions\Server;
use App\Enums\ServerStatus;
use App\Facades\Notifier;
use App\Models\Server;
use App\Notifications\ServerDisconnected;
@ -15,12 +16,12 @@ public function check(Server $server): Server
try {
$server->ssh()->connect();
$server->refresh();
if ($status == 'disconnected') {
$server->status = 'ready';
if (in_array($status, [ServerStatus::DISCONNECTED, ServerStatus::UPDATING])) {
$server->status = ServerStatus::READY;
$server->save();
}
} catch (Throwable) {
$server->status = 'disconnected';
$server->status = ServerStatus::DISCONNECTED;
$server->save();
Notifier::send($server, new ServerDisconnected($server));
}

View File

@ -0,0 +1,25 @@
<?php
namespace App\Actions\Server;
use App\Enums\ServerStatus;
use App\Facades\Notifier;
use App\Models\Server;
use App\Notifications\ServerUpdateFailed;
class Update
{
public function update(Server $server): void
{
$server->status = ServerStatus::UPDATING;
$server->save();
dispatch(function () use ($server) {
$server->os()->upgrade();
$server->checkConnection();
$server->checkForUpdates();
})->catch(function () use ($server) {
Notifier::send($server, new ServerUpdateFailed($server));
$server->checkConnection();
})->onConnection('ssh');
}
}

View File

@ -11,4 +11,6 @@ final class ServerStatus
const INSTALLATION_FAILED = 'installation_failed';
const DISCONNECTED = 'disconnected';
const UPDATING = 'updating';
}

View File

@ -4,6 +4,7 @@
use App\Actions\Server\EditServer;
use App\Actions\Server\RebootServer;
use App\Actions\Server\Update;
use App\Facades\Toast;
use App\Helpers\HtmxResponse;
use App\Models\Server;
@ -64,4 +65,24 @@ public function edit(Request $request, Server $server): RedirectResponse
return back();
}
public function checkUpdates(Server $server): RedirectResponse
{
$this->authorize('manage', $server);
$server->checkForUpdates();
return back();
}
public function update(Server $server): HtmxResponse
{
$this->authorize('manage', $server);
app(Update::class)->update($server);
Toast::info('Updating server. This may take a few minutes.');
return htmx()->back();
}
}

View File

@ -9,6 +9,7 @@
use App\SSH\Cron\Cron;
use App\SSH\OS\OS;
use App\SSH\Systemd\Systemd;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
@ -55,6 +56,8 @@
* @property Queue[] $daemons
* @property SshKey[] $sshKeys
* @property string $hostname
* @property int $updates
* @property Carbon $last_update_check
*/
class Server extends AbstractModel
{
@ -82,6 +85,8 @@ class Server extends AbstractModel
'security_updates',
'progress',
'progress_step',
'updates',
'last_update_check',
];
protected $casts = [
@ -95,6 +100,8 @@ class Server extends AbstractModel
'available_updates' => 'integer',
'security_updates' => 'integer',
'progress' => 'integer',
'updates' => 'integer',
'last_update_check' => 'datetime',
];
protected $hidden = [
@ -384,4 +391,11 @@ public function cron(): Cron
{
return new Cron($this);
}
public function checkForUpdates(): void
{
$this->updates = $this->os()->availableUpdates();
$this->last_update_check = now();
$this->save();
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Notifications;
use App\Models\Server;
use Illuminate\Notifications\Messages\MailMessage;
class ServerUpdateFailed extends AbstractNotification
{
protected Server $server;
public function __construct(Server $server)
{
$this->server = $server;
}
public function rawText(): string
{
return __("Update failed for server [:server] \nCheck your server's logs \n:logs", [
'server' => $this->server->name,
'logs' => url('/servers/'.$this->server->id.'/logs'),
]);
}
public function toEmail(object $notifiable): MailMessage
{
return (new MailMessage)
->subject(__('Server update failed!'))
->line('Your server ['.$this->server->name.'] update has been failed.')
->line('Check your server logs')
->action('View Logs', url('/servers/'.$this->server->id.'/logs'));
}
}

View File

@ -30,6 +30,19 @@ public function upgrade(): void
);
}
public function availableUpdates(): int
{
$result = $this->server->ssh()->exec(
$this->getScript('available-updates.sh'),
'check-available-updates'
);
// -1 because the first line is not a package
$availableUpdates = str($result)->after('Available updates:')->trim()->toInteger() - 1;
return max($availableUpdates, 0);
}
public function createUser(string $user, string $password, string $key): void
{
$this->server->ssh()->exec(

View File

@ -0,0 +1,5 @@
sudo DEBIAN_FRONTEND=noninteractive apt-get update
AVAILABLE_UPDATES=$(sudo DEBIAN_FRONTEND=noninteractive apt list --upgradable | wc -l)
echo "Available updates:$AVAILABLE_UPDATES"

View File

@ -1,3 +1,8 @@
sudo DEBIAN_FRONTEND=noninteractive apt-get install -y software-properties-common curl zip unzip git gcc openssl
git config --global user.email "__email__"
git config --global user.name "__name__"
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -;
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install nodejs -y

View File

@ -2,8 +2,3 @@ sudo DEBIAN_FRONTEND=noninteractive apt-get clean
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get upgrade -y
sudo DEBIAN_FRONTEND=noninteractive apt-get autoremove -y
# Install Node.js
curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash -;
sudo DEBIAN_FRONTEND=noninteractive apt-get update
sudo DEBIAN_FRONTEND=noninteractive apt-get install nodejs -y