From f7150a1d6c9dca9eb2056d530605889d708172bb Mon Sep 17 00:00:00 2001 From: Cornelis Terblanche Date: Wed, 3 Jun 2026 21:20:56 +0200 Subject: [PATCH] Fix Vultr power controls for stopped instances --- app/Services/VultrService.php | 2 +- resources/views/livewire/server/show.blade.php | 2 +- tests/Feature/VultrServerLifecycleTest.php | 17 +++++++++++++++++ tests/Unit/VultrServiceTest.php | 14 ++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/app/Services/VultrService.php b/app/Services/VultrService.php index b6d2494b6..6e1559f98 100644 --- a/app/Services/VultrService.php +++ b/app/Services/VultrService.php @@ -31,7 +31,7 @@ private function request(string $method, string $endpoint, array $data = []): ar throw new \Exception('Vultr API error: '.$response->json('error', 'Unknown error'), $response->status()); } - return $response->json(); + return $response->json() ?? []; } private function requestPaginated(string $endpoint, string $resourceKey, array $data = []): array diff --git a/resources/views/livewire/server/show.blade.php b/resources/views/livewire/server/show.blade.php index 7db1c8df3..e9a27eb39 100644 --- a/resources/views/livewire/server/show.blade.php +++ b/resources/views/livewire/server/show.blade.php @@ -140,7 +140,7 @@ class="mx-1 dark:hover:fill-white fill-black dark:fill-warning"> - @if ($server->cloudProviderToken && !$server->isFunctional() && $vultrInstanceStatus === 'stopped') + @if ($server->cloudProviderToken && $vultrInstanceStatus === 'stopped') Power On diff --git a/tests/Feature/VultrServerLifecycleTest.php b/tests/Feature/VultrServerLifecycleTest.php index e1b72a7f7..c89ca47b4 100644 --- a/tests/Feature/VultrServerLifecycleTest.php +++ b/tests/Feature/VultrServerLifecycleTest.php @@ -236,6 +236,23 @@ function vultrLifecycleTestPrivateKey(): string ]); }); +it('shows Vultr power on button when stopped even if server was previously functional', function () { + $this->server->update([ + 'ip' => '1.2.3.5', + 'vultr_instance_status' => 'stopped', + ]); + $this->server->settings->update([ + 'is_reachable' => true, + 'is_usable' => true, + 'force_disabled' => false, + ]); + + expect($this->server->fresh()->isFunctional())->toBeTrue(); + + Livewire::test(Show::class, ['server_uuid' => $this->server->uuid]) + ->assertSee('Power On'); +}); + it('starts a Vultr instance', function () { Http::fake([ 'https://api.vultr.com/v2/instances/instance-1/start' => Http::response([], 204), diff --git a/tests/Unit/VultrServiceTest.php b/tests/Unit/VultrServiceTest.php index 8fa27eb54..67f13f5a3 100644 --- a/tests/Unit/VultrServiceTest.php +++ b/tests/Unit/VultrServiceTest.php @@ -136,3 +136,17 @@ ->and($service->findInstanceByIp('2001:db8::1')['id'])->toBe('instance-1') ->and($service->findInstanceByIp('1.2.3.4'))->toBeNull(); }); + +it('handles empty successful responses from Vultr API', function () { + Http::fake([ + 'https://api.vultr.com/v2/instances/instance-1/start' => Http::response(null, 204), + 'https://api.vultr.com/v2/instances/instance-1' => Http::response(null, 204), + ]); + + $service = new VultrService('fake-token'); + + expect($service->startInstance('instance-1'))->toBe([]); + $service->deleteInstance('instance-1'); + + Http::assertSentCount(2); +});