Files
keystone/tests/Feature/ServerControllerTest.php
Harry Bayliss 5b977c1f41
Some checks failed
CI / Lint (push) Failing after 22s
CI / Tests (push) Failing after 33s
wowowowowo
2026-05-28 15:15:41 +01:00

168 lines
6.3 KiB
PHP

<?php
use App\Actions\FirewallRules\InstallFirewallRule;
use App\Actions\FirewallRules\UninstallFirewallRule;
use App\Enums\FirewallRuleType;
use App\Enums\OperationKind;
use App\Enums\OperationStatus;
use App\Enums\ServerStatus;
use App\Models\FirewallRule;
use App\Models\Organisation;
use App\Models\Provider;
use App\Models\Server;
use App\Models\User;
use Inertia\Testing\AssertableInertia;
use function Pest\Laravel\mock;
it('lists private network membership on the servers index', function () {
$user = User::factory()->create();
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
$provider = Provider::factory()->forOrganisation($organisation)->create();
$network = $organisation->networks()->create([
'provider_id' => $provider->id,
'external_id' => 'network-1',
'network_zone' => 'eu-central',
'name' => 'keystone-eu-central',
'ip_range' => '10.42.0.0/16',
]);
$server = Server::factory()
->forOrganisation($organisation->id)
->forProvider((string) $provider->id)
->forNetwork((string) $network->id)
->create([
'name' => 'app-1',
'private_ip' => '10.42.0.10',
]);
$this->actingAs($user)
->get(route('servers.index', $organisation))
->assertOk()
->assertInertia(fn (AssertableInertia $page) => $page
->component('servers/Index', false)
->where('networks.0.name', 'keystone-eu-central')
->where('networks.0.servers.0.id', $server->id)
->where('networks.0.servers.0.private_ip', '10.42.0.10'));
});
it('queues a server heal operation for failed provisioning', function () {
$user = User::factory()->create();
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
$provider = Provider::factory()->forOrganisation($organisation)->create();
$network = $organisation->networks()->create([
'provider_id' => $provider->id,
'external_id' => 'network-1',
'network_zone' => 'global',
'name' => 'keystone-global',
'ip_range' => '10.0.0.0/16',
]);
$server = Server::factory()
->forOrganisation($organisation->id)
->forProvider((string) $provider->id)
->forNetwork((string) $network->id)
->create([
'status' => ServerStatus::PROVISIONING_FAILED,
'user' => 'keystone',
]);
$this->actingAs($user)
->get(route('servers.show', [$organisation, $server]))
->assertOk()
->assertInertia(fn (AssertableInertia $page) => $page
->component('servers/Show', false)
->where('server.status', ServerStatus::PROVISIONING_FAILED->value));
$this->actingAs($user)
->post(route('servers.heal', [$organisation, $server]))
->assertRedirect(route('servers.show', [$organisation, $server]));
$operation = $server->operations()->with('steps')->firstOrFail();
expect($operation->kind)->toBe(OperationKind::SERVER_PROVISION)
->and($operation->status)->toBe(OperationStatus::PENDING)
->and($operation->steps)->toHaveCount(3)
->and($operation->steps->pluck('name')->all())->toBe([
'Check server shell',
'Check Docker',
'Check Keystone directories',
]);
});
it('creates and removes server firewall rules from the server page', function () {
mock(InstallFirewallRule::class)->shouldReceive('execute')->andReturnNull();
$user = User::factory()->create();
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
$provider = Provider::factory()->forOrganisation($organisation)->create();
$network = $organisation->networks()->create([
'provider_id' => $provider->id,
'external_id' => 'network-1',
'network_zone' => 'global',
'name' => 'keystone-global',
'ip_range' => '10.0.0.0/16',
]);
$server = Server::factory()
->forOrganisation($organisation->id)
->forProvider((string) $provider->id)
->forNetwork((string) $network->id)
->create(['user' => 'keystone']);
$this->actingAs($user)
->post(route('servers.firewall-rules.store', [$organisation, $server]), [
'type' => FirewallRuleType::ALLOW->value,
'ports' => '443/tcp',
'from' => '10.0.0.0/16',
])
->assertRedirect(route('servers.show', [$organisation, $server]));
$rule = $server->firewallRules()->firstOrFail();
expect($rule->type)->toBe(FirewallRuleType::ALLOW)
->and($rule->ports)->toBe('443/tcp')
->and($rule->from)->toBe('10.0.0.0/16');
$this->actingAs($user)
->get(route('servers.show', [$organisation, $server]))
->assertOk()
->assertInertia(fn (AssertableInertia $page) => $page
->component('servers/Show', false)
->has('server.firewall_rules', 1)
->where('server.firewall_rules.0.ports', '443/tcp'));
mock(UninstallFirewallRule::class)->shouldReceive('execute')->once();
$this->actingAs($user)
->delete(route('servers.firewall-rules.destroy', [$organisation, $server, $rule]))
->assertRedirect(route('servers.show', [$organisation, $server]));
expect(FirewallRule::query()->whereKey($rule->id)->exists())->toBeFalse();
});
it('validates server firewall rules', function () {
$user = User::factory()->create();
$organisation = Organisation::factory()->create(['owner_id' => $user->id]);
$provider = Provider::factory()->forOrganisation($organisation)->create();
$network = $organisation->networks()->create([
'provider_id' => $provider->id,
'external_id' => 'network-1',
'network_zone' => 'global',
'name' => 'keystone-global',
'ip_range' => '10.0.0.0/16',
]);
$server = Server::factory()
->forOrganisation($organisation->id)
->forProvider((string) $provider->id)
->forNetwork((string) $network->id)
->create(['user' => 'keystone']);
$this->actingAs($user)
->post(route('servers.firewall-rules.store', [$organisation, $server]), [
'type' => 'open',
'ports' => '443 tcp',
'from' => 'not a source',
])
->assertInvalid(['type', 'ports', 'from']);
expect($server->firewallRules()->exists())->toBeFalse();
});