76 lines
3.3 KiB
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();
|
|
});
|