116 lines
3.9 KiB
PHP
116 lines
3.9 KiB
PHP
<?php
|
|
|
|
use App\Enums\OperationKind;
|
|
use App\Enums\ServiceCategory;
|
|
use App\Enums\ServiceType;
|
|
use App\Models\Network;
|
|
use App\Models\Organisation;
|
|
use App\Models\Provider;
|
|
use App\Models\Server;
|
|
use App\Models\Service;
|
|
use App\Models\User;
|
|
use App\Services\Operations\RemoteCommandRunner;
|
|
use Inertia\Testing\AssertableInertia;
|
|
|
|
it('shows the stateful service update page with backup capability', function () {
|
|
[$user, $organisation, $server, $service] = serviceUpdateFixture([
|
|
'backup_enabled' => true,
|
|
'backup_command' => 'pg_dump keystone',
|
|
]);
|
|
|
|
$response = $this->actingAs($user)->get(route('service-updates.create', [
|
|
'organisation' => $organisation->id,
|
|
'server' => $server->id,
|
|
'service' => $service->id,
|
|
]));
|
|
|
|
$response->assertOk();
|
|
$response->assertInertia(fn (AssertableInertia $page) => $page
|
|
->component('services/updates/Create', false)
|
|
->where('backupAvailable', true)
|
|
->where('service.id', $service->id));
|
|
});
|
|
|
|
it('stores an explicit stateful update operation', function () {
|
|
[$user, $organisation, $server, $service] = serviceUpdateFixture([
|
|
'backup_enabled' => true,
|
|
'backup_command' => 'pg_dump keystone',
|
|
]);
|
|
|
|
$response = $this->actingAs($user)->post(route('service-updates.store', [
|
|
'organisation' => $organisation->id,
|
|
'server' => $server->id,
|
|
'service' => $service->id,
|
|
]), [
|
|
'image_digest' => 'sha256:newdigest',
|
|
'backup_requested' => true,
|
|
'confirmation' => 'postgres',
|
|
]);
|
|
|
|
$response->assertRedirect(route('servers.show', [
|
|
'organisation' => $organisation->id,
|
|
'server' => $server->id,
|
|
]));
|
|
|
|
$operation = $service->operations()->first();
|
|
|
|
expect($operation->kind)->toBe(OperationKind::SERVICE_DEPLOY)
|
|
->and($operation->steps()->where('name', 'Run pre-update backup')->exists())->toBeTrue()
|
|
->and($service->refresh()->available_image_digest)->toBe('sha256:newdigest')
|
|
->and($service->update_status)->toBe('update_pending');
|
|
});
|
|
|
|
it('resolves the latest service image digest from the update page', function () {
|
|
app()->instance(RemoteCommandRunner::class, new class implements RemoteCommandRunner
|
|
{
|
|
public function run(Server $server, string $script): string
|
|
{
|
|
return "image_digest=postgres:18@sha256:resolveddigest\n";
|
|
}
|
|
});
|
|
|
|
[$user, $organisation, $server, $service] = serviceUpdateFixture([
|
|
'backup_enabled' => true,
|
|
]);
|
|
|
|
$this->actingAs($user)
|
|
->post(route('service-updates.resolve', [$organisation, $server, $service]))
|
|
->assertRedirect(route('service-updates.create', [$organisation, $server, $service]));
|
|
|
|
expect($service->refresh()->available_image_digest)->toBe('sha256:resolveddigest');
|
|
});
|
|
|
|
/**
|
|
* @return array{0: User, 1: Organisation, 2: Server, 3: Service}
|
|
*/
|
|
function serviceUpdateFixture(array $serviceConfig = []): array
|
|
{
|
|
$user = User::factory()->create();
|
|
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
|
|
$provider = Provider::factory()->forOrganisation($organisation)->create();
|
|
$network = Network::create([
|
|
'organisation_id' => $organisation->id,
|
|
'provider_id' => $provider->id,
|
|
'name' => 'test-network',
|
|
'ip_range' => '10.0.0.0/24',
|
|
]);
|
|
$server = Server::factory()
|
|
->forOrganisation($organisation->id)
|
|
->forProvider($provider->id)
|
|
->forNetwork($network->id)
|
|
->create();
|
|
$service = Service::factory()->create([
|
|
'organisation_id' => $organisation->id,
|
|
'server_id' => $server->id,
|
|
'name' => 'postgres',
|
|
'category' => ServiceCategory::DATABASE,
|
|
'type' => ServiceType::POSTGRES,
|
|
'version' => '18',
|
|
'version_track' => '18',
|
|
'driver_name' => 'postgres.18',
|
|
'config' => $serviceConfig,
|
|
]);
|
|
|
|
return [$user, $organisation, $server, $service];
|
|
}
|