100 lines
4.4 KiB
PHP
100 lines
4.4 KiB
PHP
<?php
|
|
|
|
use App\Models\Host;
|
|
use App\Models\Instance;
|
|
use App\Models\Order;
|
|
use App\Models\ProvisioningRun;
|
|
use App\Models\SubscriptionAddon;
|
|
use App\Provisioning\Steps\Customer\ResizeVirtualMachine;
|
|
use App\Services\Billing\AddonCatalogue;
|
|
|
|
/**
|
|
* Was ein Block auf der Platte bedeutet.
|
|
*
|
|
* Der Kopfraum wächst mit der Instanz (max(10 GB, 12 %)), sonst gilt die Regel
|
|
* nur für frisch gekaufte Pakete und nicht für gestapelte. Eine volle Platte
|
|
* legt nicht den Upload still, sondern die Instanz.
|
|
*
|
|
* Absichtlich KEIN Test, der die Formel aus `growDisk()` isoliert nachrechnet:
|
|
* so eine Fassung wäre grün geblieben, selbst wenn der Schritt eine andere,
|
|
* falsche Formel benutzt hätte — und eine erste Fassung dieser Datei ist genau
|
|
* daran gescheitert (die nachgerechnete Zeile hatte kein `max(0, …)` um den
|
|
* neuen Summanden, der echte Code in `ResizeVirtualMachine.php` hat eins). Der
|
|
* einzige Test hier fährt den Schritt selbst und liest ab, was er tatsächlich
|
|
* tut.
|
|
*/
|
|
|
|
/**
|
|
* Ein frisch reservierter 'start'-Lauf: 30 GB Kontingent, 40 GB Platte
|
|
* (`database/migrations/2026_08_01_000004_switch_to_new_plan_ladder.php`),
|
|
* kein Block gebucht.
|
|
*
|
|
* Absichtlich eine eigene, in sich geschlossene Hilfsfunktion statt
|
|
* `reservedRun()` aus `CustomerStepsTest.php` zu teilen: diese Datei muss auch
|
|
* ALLEIN laufen (`… test tests/Feature/Provisioning/StoragePackHeadroomTest.php`),
|
|
* nicht nur im Verbund mit einer Nachbardatei, die zufällig zuerst geladen
|
|
* wurde. Jede andere Datei in diesem Verzeichnis bringt ihre Hilfsfunktionen
|
|
* ebenso selbst mit (`hostRun()`, `restartableInstance()`,
|
|
* `paidOrderWithSubscription()`) — geteilt wird nur, was in `tests/Pest.php`
|
|
* steht, das Pest immer lädt.
|
|
*/
|
|
function packHeadroomRun(): array
|
|
{
|
|
$host = Host::factory()->active()->create(['datacenter' => 'fsn', 'node' => 'pve']);
|
|
$order = Order::factory()->withSubscription()->create(['datacenter' => 'fsn', 'plan' => 'start']);
|
|
// Größe aus dem Vertrag, nicht aus den Vorgaben der Fabrik: so schreibt sie
|
|
// ReserveResources, und die Vorgaben der Fabrik beschreiben noch das alte
|
|
// Startpaket (100 GB auf 120). Ein Lauf, der von dort ausginge, prüfte den
|
|
// Kopfraum eines Pakets, das es nicht mehr gibt.
|
|
$instance = Instance::factory()->create([
|
|
'order_id' => $order->id, 'customer_id' => $order->customer_id,
|
|
'host_id' => $host->id, 'vmid' => 101, 'status' => 'provisioning',
|
|
'quota_gb' => $order->subscription->quota_gb,
|
|
'disk_gb' => $order->subscription->disk_gb,
|
|
]);
|
|
$run = ProvisioningRun::factory()->create([
|
|
'subject_type' => Order::class, 'subject_id' => $order->id, 'pipeline' => 'customer',
|
|
'context' => [
|
|
'instance_id' => $instance->id, 'host_id' => $host->id, 'node' => 'pve',
|
|
'vmid' => 101, 'subdomain' => $instance->subdomain, 'plan' => 'start',
|
|
],
|
|
]);
|
|
|
|
return compact('host', 'order', 'instance', 'run');
|
|
}
|
|
|
|
// Drei Blöcke à 20 GB nutzbar / 22 GB belegt kommen direkt als
|
|
// SubscriptionAddon-Zeile dazu, statt über BookAddon zu buchen — das würde
|
|
// einen Lieferlauf anstoßen und Stripe befragen, was hier nichts zur Sache
|
|
// tut; gefragt ist nur, was ResizeVirtualMachine aus einer bereits gebuchten
|
|
// Zeile macht.
|
|
//
|
|
// Ziel: 30 (Kontingent) + 60 (drei Blöcke à 20) + 10 (Kopfraum des Pakets,
|
|
// 40-30) + 6 (Kopfraum der Blöcke, 66-60 belegt) = 106 GB.
|
|
it('vergrößert die Platte um Paket- und Block-Kopfraum, und nur einmal', function () {
|
|
$s = fakeServices();
|
|
['run' => $run, 'instance' => $instance, 'order' => $order] = packHeadroomRun();
|
|
|
|
SubscriptionAddon::create([
|
|
'subscription_id' => $order->subscription->id,
|
|
'addon_key' => AddonCatalogue::STORAGE,
|
|
'price_cents' => 1000,
|
|
'currency' => 'EUR',
|
|
'quantity' => 3,
|
|
'booked_at' => now(),
|
|
'pack_gb' => 20,
|
|
'pack_disk_gb' => 22,
|
|
]);
|
|
|
|
expect(app(ResizeVirtualMachine::class)->execute($run)->type)->toBe('advance')
|
|
->and($s['pve']->resizeCalls)->toContain('101:scsi0:106G')
|
|
->and($instance->fresh()->disk_gb)->toBe(106);
|
|
|
|
// Wiederholungslauf: das Ziel ist absolut, nicht '+…', also darf ein
|
|
// zweiter Durchlauf nicht noch einmal vergrößern.
|
|
$s['pve']->resizeCalls = [];
|
|
expect(app(ResizeVirtualMachine::class)->execute($run->fresh())->type)->toBe('advance')
|
|
->and($s['pve']->resizeCalls)->toBe([])
|
|
->and($instance->fresh()->disk_gb)->toBe(106);
|
|
});
|