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(); });