fix(servers): refresh provider status with server details action

This commit is contained in:
Andras Bacsai
2026-11-01 15:49:13 +01:00
parent 868c0f06bf
commit 23eebbf2ad
3 changed files with 50 additions and 33 deletions
+28 -1
View File
@@ -850,8 +850,11 @@ class Show extends Component
{
try {
$this->authorize('update', $this->server);
$providerRefreshed = $this->refreshProviderStatus();
if (! $this->server->isFunctional()) {
$this->dispatch('error', 'Validate the server connection before fetching details.');
$providerRefreshed
? $this->dispatch('info', 'Provider status refreshed. Validate the server connection to fetch server details.')
: $this->dispatch('error', 'Validate the server connection before fetching details.');
return;
}
@@ -868,6 +871,30 @@ class Show extends Component
}
}
/**
* Refresh the state of the linked cloud provider server, if there is one.
*/
private function refreshProviderStatus(): bool
{
if (! $this->server->cloudProviderToken || $this->server->isTransferredAway()) {
return false;
}
$check = match (true) {
filled($this->server->hetzner_server_id) => $this->checkHetznerServerStatus(...),
filled($this->server->digitalocean_droplet_id) => $this->checkDigitalOceanDropletStatus(...),
filled($this->server->vultr_instance_id) => $this->checkVultrInstanceStatus(...),
filled($this->server->hostinger_virtual_machine_id) => $this->checkHostingerVirtualMachineStatus(...),
default => null,
};
if (! $check) {
return false;
}
$check();
return true;
}
public function submit()
{
try {
+9 -29
View File
@@ -28,6 +28,7 @@
'Hostinger' => $hostingerVirtualMachineStatus,
default => null,
};
$canRefreshProvider = $provider && $server->cloudProviderToken && ! $server->isTransferredAway();
$providerStatusType = match (true) {
in_array($providerStatus, ['running', 'active']) => 'success',
in_array($providerStatus, ['starting', 'initializing', 'pending', 'new', 'initial', 'creating', 'unsuspending', 'recreating', 'restoring']) => 'warning',
@@ -265,35 +266,14 @@
<x-application.settings-section id="server-overview-section" title="Server overview"
helper="Provider state, operating system, and hardware details.">
<x-slot:actions>
@if ($provider)
@if ($provider)
<x-slot:badges>
<x-status-badge :label="$provider . ($providerStatus ? ' · ' . ucfirst($providerStatus) : '')"
:type="$providerStatusType" />
@if ($provider === 'Hetzner')
<x-forms.button type="button" class="size-8! px-0!"
wire:click.prevent="checkHetznerServerStatus(true)"
title="Refresh provider status">
<x-reicon name="refresh" class="size-3.5" />
</x-forms.button>
@elseif ($provider === 'DigitalOcean')
<x-forms.button type="button" class="size-8! px-0!"
wire:click.prevent="checkDigitalOceanDropletStatus(true)"
title="Refresh provider status">
<x-reicon name="refresh" class="size-3.5" />
</x-forms.button>
@elseif ($provider === 'Vultr')
<x-forms.button type="button" class="size-8! px-0!"
wire:click.prevent="checkVultrInstanceStatus(true)"
title="Refresh provider status">
<x-reicon name="refresh" class="size-3.5" />
</x-forms.button>
@elseif ($provider === 'Hostinger')
<x-forms.button type="button" class="size-8! px-0!"
wire:click.prevent="checkHostingerVirtualMachineStatus(true)"
title="Refresh provider status">
<x-reicon name="refresh" class="size-3.5" />
</x-forms.button>
@endif
</x-slot:badges>
@endif
<x-slot:actions>
@if ($provider)
@if ($server->cloudProviderToken && ! $server->isTransferredAway())
@if ($provider === 'Hetzner' && !$server->isFunctional() && $hetznerServerStatus === 'off')
<x-forms.button type="button" wire:click.prevent="startHetznerServer" isHighlighted
@@ -314,8 +294,8 @@
@endif
@endif
<x-forms.button type="button" wire:click="refreshServerMetadata"
:disabled="! $server->isFunctional()"
:tooltip="$server->isFunctional() ? null : 'Validate the connection first.'">
:disabled="! $server->isFunctional() && ! $canRefreshProvider"
:tooltip="$server->isFunctional() || $canRefreshProvider ? null : 'Validate the connection first.'">
<x-reicon name="refresh" class="size-3.5" />
{{ $server->server_metadata ? 'Refresh details' : 'Fetch server details' }}
</x-forms.button>
+13 -3
View File
@@ -407,7 +407,7 @@ it('starts a stopped Hostinger VPS from the server page', function () {
expect($server->fresh()->hostinger_virtual_machine_status)->toBe('starting');
});
it('labels the Hostinger status refresh button on the server page', function () {
it('refreshes the Hostinger status from the server details action before the server is validated', function () {
$server = Server::factory()->create([
'team_id' => $this->team->id,
'private_key_id' => $this->privateKey->id,
@@ -416,10 +416,20 @@ it('labels the Hostinger status refresh button on the server page', function ()
'hostinger_virtual_machine_status' => 'running',
]);
Http::fake([
'https://developers.hostinger.com/api/vps/v1/virtual-machines/17923' => Http::response([
'id' => 17923,
'state' => 'stopped',
'ipv4' => [['address' => $server->ip]],
]),
]);
Livewire::test(Show::class, ['server_uuid' => $server->uuid])
->assertSee('Hostinger · Running')
->assertSee('Refresh provider status')
->assertSeeHtml('wire:click.prevent="checkHostingerVirtualMachineStatus(true)"');
->call('refreshServerMetadata')
->assertSet('hostingerVirtualMachineStatus', 'stopped')
->assertDispatched('info', 'Provider status refreshed. Validate the server connection to fetch server details.')
->assertSee('Hostinger · Stopped');
});
it('does not validate a stopped Hostinger VPS over SSH', function () {