81 lines
3.4 KiB
PHP
81 lines
3.4 KiB
PHP
<?php
|
|
|
|
use App\Actions\Services\CreateStatefulServiceUpdateOperation;
|
|
use App\Enums\ServiceCategory;
|
|
use App\Enums\ServiceType;
|
|
use App\Models\Service;
|
|
|
|
it('creates explicit downtime-aware update operations for postgres', function () {
|
|
$service = Service::factory()->create([
|
|
'name' => 'postgres',
|
|
'category' => ServiceCategory::DATABASE,
|
|
'type' => ServiceType::POSTGRES,
|
|
'version' => '18',
|
|
'version_track' => '18',
|
|
'driver_name' => 'postgres.18',
|
|
'current_image_digest' => 'sha256:old',
|
|
'config' => [
|
|
'backup_enabled' => true,
|
|
'backup_command' => 'pg_dump --format=custom keystone > /home/keystone/backups/pre-update.dump',
|
|
],
|
|
]);
|
|
|
|
$operation = app(CreateStatefulServiceUpdateOperation::class)->execute(
|
|
service: $service,
|
|
imageDigest: 'sha256:new',
|
|
backupRequested: true,
|
|
);
|
|
|
|
expect($service->refresh()->available_image_digest)->toBe('sha256:new')
|
|
->and($service->update_status)->toBe('update_pending')
|
|
->and($operation->steps()->pluck('name')->all())
|
|
->toBe([
|
|
'Acknowledge downtime and data risk',
|
|
'Run pre-update backup',
|
|
'Render compose with updated image digest',
|
|
'Stop existing container',
|
|
'Preserve named volume',
|
|
'Start service with updated image digest',
|
|
'Health check updated service',
|
|
])
|
|
->and($operation->steps()->where('name', 'Run pre-update backup')->first()->script)
|
|
->toBe('pg_dump --format=custom keystone > /home/keystone/backups/pre-update.dump')
|
|
->and($operation->steps()->where('name', 'Render compose with updated image digest')->first()->script)
|
|
->toContain('base64 -d')
|
|
->and($operation->steps()->where('name', 'Stop existing container')->first()->script)
|
|
->toBe("docker compose -f /home/keystone/services/{$service->id}/compose.yml stop {$service->name}")
|
|
->and($operation->steps()->where('name', 'Preserve named volume')->first()->script)
|
|
->toBe("docker volume inspect keystone_service_{$service->id}_postgres_data >/dev/null")
|
|
->and($operation->steps()->where('name', 'Health check updated service')->first()->script)
|
|
->toContain('docker inspect --format');
|
|
});
|
|
|
|
it('rejects backup requests when no backup capability is configured', function () {
|
|
$service = Service::factory()->create([
|
|
'category' => ServiceCategory::DATABASE,
|
|
'type' => ServiceType::POSTGRES,
|
|
'version' => '18',
|
|
'version_track' => '18',
|
|
'driver_name' => 'postgres.18',
|
|
'config' => [
|
|
'backup_enabled' => false,
|
|
],
|
|
]);
|
|
|
|
expect(fn () => app(CreateStatefulServiceUpdateOperation::class)->execute($service, 'sha256:new', backupRequested: true))
|
|
->toThrow(InvalidArgumentException::class, 'Backups are not configured for this service.');
|
|
});
|
|
|
|
it('rejects stateful update operations for stateless laravel services', function () {
|
|
$service = Service::factory()->create([
|
|
'category' => ServiceCategory::APPLICATION,
|
|
'type' => ServiceType::LARAVEL,
|
|
'version' => 'php-8.4',
|
|
'version_track' => 'php-8.4',
|
|
'driver_name' => 'laravel.php-8.4',
|
|
]);
|
|
|
|
expect(fn () => app(CreateStatefulServiceUpdateOperation::class)->execute($service, 'sha256:new'))
|
|
->toThrow(InvalidArgumentException::class, 'Only Postgres and Valkey have v1 stateful update operations.');
|
|
});
|