Fix-Runde 1: Formel-Test raus, eigene Testhilfe, Docblock nachgezogen
Der Formel-Test rechnete dieselbe Formel nach und wich dabei vom echten Code ab (kein max(0, ...) um den neuen Summanden) — ein Test, der die Implementierung nachrechnet und dabei abweicht, ist schlechter als keiner. Der Verhaltenstest deckt die Anforderung bereits ab und bleibt als einziger Test der Datei. StoragePackHeadroomTest.php hing außerdem an reservedRun() aus CustomerStepsTest.php und brach einzeln gefahren mit einem PHP-Fatal ab, statt mit einem ehrlichen Fehlschlag. Eigene, in sich geschlossene Hilfsfunktion (packHeadroomRun()) nach dem Muster der Nachbardateien (hostRun(), restartableInstance()) — die Datei läuft jetzt auch allein grün. Der Docblock von growDisk() sprach noch vom Kopfraum, der "unchanged" mitfährt, und widersprach damit dem neuen Summanden direkt darunter. Nachgezogen. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>feat/neue-pakete
parent
3ed80a05e0
commit
d6f2aa1c9e
|
|
@ -85,13 +85,17 @@ class ResizeVirtualMachine extends CustomerStep
|
|||
* when that is less than the machine already has.
|
||||
*
|
||||
* The target is the customer's WHOLE allowance — package plus booked storage
|
||||
* packs — with the package's own system overhead left on top of it. That
|
||||
* overhead is read off the package and never invented: the catalogue's four
|
||||
* packages ship 120/100, 540/500, 1050/1000 and 2100/2000 GB, which is 20,
|
||||
* 40, 50 and 100 GB of room beside the customer's files and is a decision the
|
||||
* owner makes per package, not a ratio anybody may derive. A pack of extra
|
||||
* storage is that much more FOR THE CUSTOMER, so it is added to the
|
||||
* allowance and the package's overhead rides along unchanged.
|
||||
* packs — with TWO overheads left on top of it, never one. The package's own
|
||||
* system overhead is read off the package and never invented: the catalogue's
|
||||
* four packages ship 120/100, 540/500, 1050/1000 and 2100/2000 GB, which is
|
||||
* 20, 40, 50 and 100 GB of room beside the customer's files and is a decision
|
||||
* the owner makes per package, not a ratio anybody may derive. Every booked
|
||||
* pack brings ITS OWN overhead the same way, frozen on the booking rather
|
||||
* than on the package — what it gives the customer and what it takes on the
|
||||
* host are two different figures, and only their difference belongs here.
|
||||
* Without it, a stack of packs would sit on the package's headroom alone and
|
||||
* thin it out with every pack added, which is exactly the shape the rule
|
||||
* exists to refuse.
|
||||
*
|
||||
* With no packs booked the sum is exactly the package's own `disk_gb`, which
|
||||
* is what this step has always used.
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
<?php
|
||||
|
||||
use App\Models\Host;
|
||||
use App\Models\Instance;
|
||||
use App\Models\Order;
|
||||
use App\Models\ProvisioningRun;
|
||||
use App\Models\SubscriptionAddon;
|
||||
use App\Services\Billing\AddonCatalogue;
|
||||
use App\Services\Billing\StorageAllowance;
|
||||
use App\Provisioning\Steps\Customer\ResizeVirtualMachine;
|
||||
use App\Services\Billing\AddonCatalogue;
|
||||
|
||||
/**
|
||||
* Was ein Block auf der Platte bedeutet.
|
||||
|
|
@ -12,35 +14,60 @@ use App\Provisioning\Steps\Customer\ResizeVirtualMachine;
|
|||
* 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.
|
||||
*/
|
||||
it('rechnet Kopfraum des Pakets und der Blöcke zusammen', function () {
|
||||
// Start: 30 GB Kontingent auf 40 GB Platte. Drei Blöcke zu 20 GB nutzbar
|
||||
// und 22 GB belegt.
|
||||
$allowance = new StorageAllowance(planGb: 30, packs: 3, bookedGb: 60, bookedDiskGb: 66, packSizeGb: 20);
|
||||
|
||||
$planDisk = 40;
|
||||
$planQuota = 30;
|
||||
/**
|
||||
* Ein frisch reservierter 'start'-Lauf: 100 GB Kontingent, 120 GB Platte
|
||||
* (`database/migrations/2026_07_26_040000_create_plan_catalogue_tables.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']);
|
||||
$instance = Instance::factory()->create([
|
||||
'order_id' => $order->id, 'customer_id' => $order->customer_id,
|
||||
'host_id' => $host->id, 'vmid' => 101, 'status' => 'provisioning',
|
||||
]);
|
||||
$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',
|
||||
],
|
||||
]);
|
||||
|
||||
$target = $allowance->totalGb()
|
||||
+ max(0, $planDisk - $planQuota)
|
||||
+ ($allowance->packDiskGb() - $allowance->packGb());
|
||||
return compact('host', 'order', 'instance', 'run');
|
||||
}
|
||||
|
||||
expect($target)->toBe(106);
|
||||
});
|
||||
|
||||
// Den Schritt selbst fahren: reservedRun() (aus CustomerStepsTest.php) baut ein
|
||||
// 'start'-Paket (100 GB Kontingent, 120 GB Platte — 20 GB Kopfraum des Pakets).
|
||||
// Drei Blöcke zu 20 GB nutzbar / 22 GB belegt kommen direkt als
|
||||
// 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.
|
||||
// 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: 100 (Kontingent) + 60 (drei Blöcke à 20) + 20 (Kopfraum des Pakets,
|
||||
// 120-100) + 6 (Kopfraum der Blöcke, 66-60 belegt) = 186 GB.
|
||||
it('vergrößert die Platte um Paket- und Block-Kopfraum, und nur einmal', function () {
|
||||
$s = fakeServices();
|
||||
['run' => $run, 'instance' => $instance, 'order' => $order] = reservedRun();
|
||||
['run' => $run, 'instance' => $instance, 'order' => $order] = packHeadroomRun();
|
||||
|
||||
SubscriptionAddon::create([
|
||||
'subscription_id' => $order->subscription->id,
|
||||
|
|
|
|||
Loading…
Reference in New Issue