mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-04 10:42:23 +00:00
Co-authored-by: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Co-authored-by: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: rosslh <ross@rosshill.ca>
128 lines
5.2 KiB
PHP
128 lines
5.2 KiB
PHP
<?php
|
|
|
|
use App\Models\InstanceSettings;
|
|
use App\Models\PrivateKey;
|
|
use App\Models\Server;
|
|
use App\Models\Team;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
use Illuminate\Support\Facades\DB;
|
|
use Illuminate\Support\Facades\Log;
|
|
|
|
uses(RefreshDatabase::class);
|
|
|
|
beforeEach(function () {
|
|
InstanceSettings::forceCreate(['id' => 0]);
|
|
$this->team = Team::factory()->create();
|
|
$this->privateKey = PrivateKey::factory()->create(['team_id' => $this->team->id]);
|
|
});
|
|
|
|
/**
|
|
* Creates a server and writes the raw IP past the model setter, like rows saved by older versions.
|
|
*/
|
|
function createServerWithRawIpForMigrationTest(Team $team, PrivateKey $privateKey, string $rawIp, array $attributes = []): Server
|
|
{
|
|
$server = Server::factory()->create(array_merge([
|
|
'team_id' => $team->id,
|
|
'private_key_id' => $privateKey->id,
|
|
'ip' => '203.0.113.250',
|
|
], $attributes));
|
|
DB::table('servers')->where('id', $server->id)->update(['ip' => $rawIp]);
|
|
|
|
return $server;
|
|
}
|
|
|
|
function runNormalizeIpv6ServerIpsMigration(): void
|
|
{
|
|
(require database_path('migrations/2026_10_09_092903_normalize_ipv6_server_ips.php'))->up();
|
|
}
|
|
|
|
function rawServerIp(Server $server): ?string
|
|
{
|
|
return DB::table('servers')->where('id', $server->id)->value('ip');
|
|
}
|
|
|
|
it('repairs Hetzner IPv6 networks saved with the old setter', function () {
|
|
$server = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2a01:4f8:c016:bd23::64', [
|
|
'hetzner_server_id' => 123,
|
|
]);
|
|
$server->settings()->update(['is_reachable' => false]);
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect(rawServerIp($server))->toBe('2a01:4f8:c016:bd23::1');
|
|
});
|
|
|
|
it('keeps a reachable Hetzner server whose address really ends in ::64', function () {
|
|
$server = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2a01:4f8:c016:bd23::64', [
|
|
'hetzner_server_id' => 123,
|
|
]);
|
|
$server->settings()->update(['is_reachable' => true]);
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect(rawServerIp($server))->toBe('2a01:4f8:c016:bd23::64');
|
|
});
|
|
|
|
it('repairs Sentinel URLs that were saved with a bare IPv6 address', function () {
|
|
$server = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2a01:4f8:c016:bd23::1');
|
|
$server->settings()->update(['sentinel_custom_url' => 'http://2a01:4f8:c016:bd23::1:8000']);
|
|
$other = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '198.51.100.8');
|
|
$other->settings()->update(['sentinel_custom_url' => 'https://coolify.example.com']);
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect($server->settings()->value('sentinel_custom_url'))->toBe('http://[2a01:4f8:c016:bd23::1]:8000')
|
|
->and($other->settings()->value('sentinel_custom_url'))->toBe('https://coolify.example.com');
|
|
});
|
|
|
|
it('ignores deleted servers when it checks for duplicates', function () {
|
|
$deleted = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2001:db8::9');
|
|
$deleted->delete();
|
|
$server = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2001:0DB8::9');
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect(rawServerIp($server))->toBe('2001:db8::9');
|
|
});
|
|
|
|
it('normalizes IPv6 addresses and leaves IPv4 addresses and hostnames untouched', function () {
|
|
$ipv6 = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2A01:04F8:0000:0000:0000:0000:0000:0001');
|
|
$notHetzner = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2001:db8::64');
|
|
$ipv4 = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '198.51.100.7');
|
|
$hostname = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, 'Server.Example.com');
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect(rawServerIp($ipv6))->toBe('2a01:4f8::1')
|
|
->and(rawServerIp($notHetzner))->toBe('2001:db8::64')
|
|
->and(rawServerIp($ipv4))->toBe('198.51.100.7')
|
|
->and(rawServerIp($hostname))->toBe('Server.Example.com');
|
|
});
|
|
|
|
it('includes the server with id 0', function () {
|
|
createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2001:0DB8::9', ['id' => 0]);
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect(DB::table('servers')->where('id', 0)->value('ip'))->toBe('2001:db8::9');
|
|
});
|
|
|
|
it('skips a server when the new address belongs to another server', function () {
|
|
Log::spy();
|
|
$existing = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2a01:4f8:c016:bd23::1');
|
|
$broken = createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2a01:4f8:c016:bd23::64', [
|
|
'hetzner_server_id' => 123,
|
|
]);
|
|
$broken->settings()->update(['is_reachable' => false]);
|
|
$otherTeam = Team::factory()->create();
|
|
$otherTeamServer = createServerWithRawIpForMigrationTest($otherTeam, PrivateKey::factory()->create(['team_id' => $otherTeam->id]), '2001:0db8::1');
|
|
createServerWithRawIpForMigrationTest($this->team, $this->privateKey, '2001:db8::1');
|
|
|
|
runNormalizeIpv6ServerIpsMigration();
|
|
|
|
expect(rawServerIp($existing))->toBe('2a01:4f8:c016:bd23::1')
|
|
->and(rawServerIp($broken))->toBe('2a01:4f8:c016:bd23::64')
|
|
->and(rawServerIp($otherTeamServer))->toBe('2001:0db8::1');
|
|
Log::shouldHaveReceived('warning')->twice();
|
|
});
|