mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-14 16:52:45 -04:00
- database import: add keep_owners (restore PostgreSQL owners and privileges) and sqlite_database (pick the target SQLite file) to the API, OpenAPI spec, and import form - oauth: require password confirmation and support team selection on OAuth login - remote process: send team broadcast events to the team of the server that ran the process instead of the causer's user id - servers API: handle the legacy build server setting - compose: support parent bind paths and volume driver options - dns: improve record hints and provider management - notifications: fix throttling and missing backup notifications - ui: rework the confirmation modal - add feature and unit tests for the new behavior
77 lines
2.8 KiB
PHP
77 lines
2.8 KiB
PHP
<?php
|
|
|
|
use App\Support\DnsRecordHints;
|
|
|
|
it('builds a and aaaa records for a single hostname', function () {
|
|
$records = DnsRecordHints::forTarget('app.example.com', '203.0.113.10', '2001:db8::1');
|
|
|
|
expect($records)->toHaveCount(2)
|
|
->and($records[0])->toMatchArray([
|
|
'type' => 'A',
|
|
'name' => 'app.example.com',
|
|
'value' => '203.0.113.10',
|
|
])
|
|
->and($records[1])->toMatchArray([
|
|
'type' => 'AAAA',
|
|
'name' => 'app.example.com',
|
|
'value' => '2001:db8::1',
|
|
]);
|
|
});
|
|
|
|
it('builds entries for every hostname without duplicates', function () {
|
|
$records = DnsRecordHints::forHostnames([
|
|
'app.example.com',
|
|
'www.example.com',
|
|
'app.example.com',
|
|
'https://api.example.com/path',
|
|
], '203.0.113.10');
|
|
|
|
expect($records)->toHaveCount(3)
|
|
->and(collect($records)->pluck('name')->all())->toBe([
|
|
'api.example.com',
|
|
'app.example.com',
|
|
'www.example.com',
|
|
])
|
|
->and(collect($records)->pluck('type')->unique()->all())->toBe(['A']);
|
|
});
|
|
|
|
it('formats a BIND-compatible zone snippet for copy all', function () {
|
|
$text = DnsRecordHints::toCopyText([
|
|
['type' => 'A', 'name' => 'app.example.com', 'value' => '203.0.113.10'],
|
|
['type' => 'A', 'name' => 'www.example.com', 'value' => '203.0.113.10'],
|
|
['type' => 'AAAA', 'name' => 'app.example.com', 'value' => '2001:db8::1'],
|
|
]);
|
|
|
|
expect($text)->toBe(
|
|
"app.example.com. IN A 203.0.113.10\n".
|
|
"www.example.com. IN A 203.0.113.10\n".
|
|
"app.example.com. IN AAAA 2001:db8::1\n"
|
|
);
|
|
});
|
|
|
|
it('treats only publicly routable addresses as public dns record targets', function (string $address, bool $public) {
|
|
expect(DnsRecordHints::isPublicAddress($address))->toBe($public);
|
|
})->with([
|
|
'public ipv4' => ['8.8.8.8', true],
|
|
'public ipv6' => ['2606:4700::1111', true],
|
|
'rfc1918 10/8' => ['10.0.0.5', false],
|
|
'rfc1918 172.16/12' => ['172.20.1.5', false],
|
|
'rfc1918 192.168/16' => ['192.168.1.5', false],
|
|
'cgnat start' => ['100.64.0.1', false],
|
|
'tailscale cgnat' => ['100.100.100.100', false],
|
|
'cgnat end' => ['100.127.255.254', false],
|
|
'just outside cgnat' => ['100.128.0.1', true],
|
|
'loopback' => ['127.0.0.1', false],
|
|
'link-local' => ['169.254.10.1', false],
|
|
'unspecified' => ['0.0.0.0', false],
|
|
'multicast' => ['224.0.0.1', false],
|
|
'ipv6 unique local' => ['fd00::5', false],
|
|
'ipv6 link-local' => ['fe80::5', false],
|
|
'ipv6 loopback' => ['::1', false],
|
|
'ipv6 multicast' => ['ff02::1', false],
|
|
'ipv4-mapped private' => ['::ffff:10.0.0.5', false],
|
|
'ipv4-mapped cgnat' => ['::ffff:100.64.0.1', false],
|
|
'not an ip' => ['app.example.com', false],
|
|
'empty' => ['', false],
|
|
]);
|