CluPilotCloud/tests/Feature/Provisioning/CustomerDataModelTest.php

76 lines
3.3 KiB
PHP

<?php
use App\Models\Host;
use App\Models\Instance;
use App\Models\Order;
use App\Models\ProvisioningRun;
use Illuminate\Database\QueryException;
it('resolves an Order as the polymorphic run subject', function () {
$order = Order::factory()->create();
$run = ProvisioningRun::factory()->create([
'subject_type' => Order::class,
'subject_id' => $order->id,
'pipeline' => 'customer',
]);
expect($run->fresh()->subject->is($order))->toBeTrue()
->and($order->getRouteKeyName())->toBe('uuid');
});
it('marks the order and releases its instance via the ProvisioningSubject hook', function () {
$order = Order::factory()->create(['status' => 'provisioning']);
$instance = Instance::factory()->create([
'order_id' => $order->id, 'customer_id' => $order->customer_id, 'status' => 'provisioning',
]);
$order->onProvisioningFailed();
expect($order->fresh()->status)->toBe('failed')
->and($instance->fresh()->status)->toBe('failed'); // quota no longer counts against capacity
});
it('enforces a unique stripe_event_id (idempotency)', function () {
Order::factory()->create(['stripe_event_id' => 'evt_123']);
Order::factory()->create(['stripe_event_id' => 'evt_123']);
})->throws(QueryException::class);
it('enforces a unique subdomain', function () {
Instance::factory()->create(['subdomain' => 'kanzlei-berger']);
Instance::factory()->create(['subdomain' => 'kanzlei-berger']);
})->throws(QueryException::class);
it('encrypts nc_admin_ref at rest', function () {
$instance = Instance::factory()->create(['nc_admin_ref' => 'admin']);
$raw = \DB::table('instances')->where('id', $instance->id)->value('nc_admin_ref');
expect($raw)->not->toBe('admin')
->and($instance->fresh()->nc_admin_ref)->toBe('admin');
});
it('computes host capacity from committed instance quotas', function () {
$host = Host::factory()->active()->create(['total_gb' => 1000, 'reserve_pct' => 15]);
// freeGb = 850
Instance::factory()->create(['host_id' => $host->id, 'quota_gb' => 100, 'status' => 'active']);
Instance::factory()->create(['host_id' => $host->id, 'quota_gb' => 200, 'status' => 'provisioning']);
Instance::factory()->create(['host_id' => $host->id, 'quota_gb' => 500, 'status' => 'failed', 'vmid' => null]); // released (no VM)
Instance::factory()->create(['host_id' => $host->id, 'quota_gb' => 150, 'status' => 'failed', 'vmid' => 900]); // VM still exists → counts
expect($host->committedGb())->toBe(450) // 100 + 200 + 150
->and($host->availableGb())->toBe(400); // 850 - 450
});
it('places an instance on an active host in the datacenter with room', function () {
$full = Host::factory()->active()->create(['datacenter' => 'fsn', 'name' => 'pve-fsn-a', 'total_gb' => 100, 'reserve_pct' => 15]);
Instance::factory()->create(['host_id' => $full->id, 'quota_gb' => 80, 'status' => 'active']);
$room = Host::factory()->active()->create(['datacenter' => 'fsn', 'name' => 'pve-fsn-b', 'total_gb' => 1000, 'reserve_pct' => 15]);
Host::factory()->active()->create(['datacenter' => 'hel', 'name' => 'pve-hel-a', 'total_gb' => 1000]);
$picked = Host::placeableIn('fsn', 100);
expect($picked?->is($room))->toBeTrue()
->and(Host::placeableIn('nowhere', 100))->toBeNull();
});