refactor(v5): defer builder bootstrap support

Remove active builder flags from dev Lima sync, bootstrap commands,
and server capabilities while documenting the v5 control-plane and
host-agent boundaries.
This commit is contained in:
Andras Bacsai committed 2026-06-21 16:54:02 +02:00
1 parent 068a2979fd
commit 4938b65f20
22 files changed
+361 -219

No files matched your search

+1 -3
View File
@@ -14,7 +14,6 @@ it('does not include coold dev tooling defaults in the development env example',
'coold VM WireGuard IP 2 default' => 'COOLIFY_COOLD_VM_WG_IP_2',
'coold VM WireGuard port 1 default' => 'COOLIFY_COOLD_VM_WG_PORT_1',
'coold VM WireGuard port 2 default' => 'COOLIFY_COOLD_VM_WG_PORT_2',
'coold VM builder capacity default' => 'COOLIFY_COOLD_VM_BUILDER_CAPACITY',
'coold VM enabled default' => 'COOLIFY_COOLD_VM_ENABLED',
'coold VM stop on down default' => 'COOLIFY_COOLD_VM_STOP_ON_DOWN',
'dev follow logs default' => 'COOLIFY_DEV_FOLLOW_LOGS',
@@ -25,8 +24,7 @@ it('defaults coold dev VM settings in Laravel config', function () {
->and(config('coold.coold_version'))->toBe('nightly')
->and(config('coold.corrosion_version'))->toBe('v1.0.0')
->and(config('coold.dev_ssh_user'))->toBe('coolify')
->and(config('coold.dev_builder_capacity'))->toBe(2)
->and(config('coold.dev_builder_enabled'))->toBeTrue();
->and(config('coold.dev_ssh_user'))->toBe('coolify');
});
it('runs the v5 dev Lima seeder with the normal development database seeder', function () {
+2 -2
View File
@@ -12,7 +12,7 @@ it('mints a host jwt signed by the configured flux private key', function () {
$exitCode = Artisan::call('flux:dev', [
'host_id' => 'coold-dev',
'--caps' => 'coold,builder',
'--caps' => 'coold',
'--ttl' => '600',
]);
@@ -23,7 +23,7 @@ it('mints a host jwt signed by the configured flux private key', function () {
expect($claims->sub)->toBe('coold-dev')
->and($claims->aud)->toBe('coold')
->and($claims->caps)->toBe(['coold', 'builder'])
->and($claims->caps)->toBe(['coold'])
->and($claims->exp)->toBeGreaterThan(time());
});
+5 -8
View File
@@ -2291,7 +2291,7 @@ it('adds a v5 server to a cluster for the current team', function () {
->assertJsonPath('cluster.servers.0.builderCpuQuota', '200%')
->assertJsonPath('cluster.servers.0.ingressEnabled', false)
->assertJsonPath('cluster.servers.0.ingressType', null)
->assertJsonPath('cluster.servers.0.capabilities', ['coold', 'builder'])
->assertJsonPath('cluster.servers.0.capabilities', ['coold'])
->assertJsonPath('cluster.servers.0.wireguardListenPortOverride', 51821)
->assertJsonPath('cluster.servers.0.wireguardEndpointOverride', 'prod-01.example.com:51821')
->assertJsonPath('cluster.servers.0.wireguardManagementIp', null)
@@ -2310,7 +2310,7 @@ it('adds a v5 server to a cluster for the current team', function () {
->exists())->toBeTrue();
expect(V5Server::query()->where('name', 'prod-01')->first()->capabilities)
->toBe(['coold', 'builder']);
->toBe(['coold']);
});
it('adds a v5 server with caddy ingress enabled', function () {
@@ -2720,7 +2720,7 @@ it('bootstraps a single v5 server with the Coolify CLI', function () {
&& cliFlagValue($command, '--corrosion-version') === 'v1.1.0'
&& cliFlagValue($command, '--wg-listen-port-overrides') === $node.'=51831'
&& cliFlagValue($command, '--wg-endpoint-overrides') === $node.'=prod-01.example.com:51831'
&& in_array('--enable-builder', $command, true)
&& ! in_array('--enable-builder', $command, true)
&& in_array('--yes', $command, true)
&& ! in_array('--new-nodes', $command, true);
});
@@ -3143,7 +3143,7 @@ it('updates editable v5 server builder details without changing networking', fun
expect($server->builder_enabled)->toBeTrue()
->and($server->builder_capacity)->toBe(5)
->and($server->builder_cpu_quota)->toBe('350%')
->and($server->capabilities)->toBe(['coold', 'builder'])
->and($server->capabilities)->toBe(['coold'])
->and($server->host)->toBe('203.0.113.10')
->and($server->ssh_user)->toBe('root')
->and($server->ssh_port)->toBe(22)
@@ -4640,7 +4640,6 @@ it('syncs dev Lima VMs into v5 clusters and servers', function () {
'--team-id' => $team->id,
'--user-id' => $user->id,
'--cluster' => 'Development-Lima',
'--builder-capacity' => 2,
'--server' => [
'coold-dev|host.docker.internal|developer|61332|100.64.0.1',
'coold-dev-2|host.docker.internal|developer|61379|100.64.0.2',
@@ -4683,7 +4682,6 @@ it('updates legacy dev Lima hostnames to Docker reachable SSH endpoints', functi
'--team-id' => $team->id,
'--user-id' => $user->id,
'--cluster' => 'Development-Lima',
'--builder-capacity' => 2,
'--server' => [
'coold-dev|host.docker.internal|developer|61332',
],
@@ -4699,7 +4697,6 @@ it('seeds dev Lima VMs into v5 clusters and servers idempotently', function () {
createSharedUserAndTeamTables();
[$user, $team] = createV5UserWithTeam();
createV5PrivateKey($team, 'Dev Lima Key');
config()->set('coold.dev_builder_capacity', 2);
(new V5DevLimaSeeder)->run();
(new V5DevLimaSeeder)->run();
@@ -4715,7 +4712,7 @@ it('seeds dev Lima VMs into v5 clusters and servers idempotently', function () {
->and(V5Server::query()->where('name', 'coold-dev')->where('node_address', '100.64.0.1')->where('wireguard_management_ip', '100.64.0.1')->exists())->toBeTrue()
->and(V5Server::query()->where('name', 'coold-dev-2')->where('node_address', '100.64.0.2')->where('wireguard_management_ip', '100.64.0.2')->exists())->toBeTrue()
->and(V5Server::query()->where('status', 'installed')->count())->toBe(2)
->and(V5Server::query()->where('builder_enabled', true)->where('builder_capacity', 2)->count())->toBe(2)
->and(V5Server::query()->where('builder_enabled', false)->where('builder_capacity', 0)->count())->toBe(2)
->and(V5Server::query()->where('cluster_id', $cluster->id)->count())->toBe(2);
});
@@ -240,3 +240,87 @@ function withFakeFluxSocket(string $response, Closure $callback): void
@unlink($socketPath);
}
}
it('dispatches container inventory through the containers list primitive', function () {
if (! function_exists('pcntl_fork')) {
$this->markTestSkipped('pcntl is required to fake a Flux Unix socket.');
}
$body = json_encode([
'request_id' => 'test-request',
'status' => 'ok',
'data' => [],
], JSON_THROW_ON_ERROR);
$requestPath = storage_path('framework/testing/flux-request-'.bin2hex(random_bytes(8)).'.txt');
withFakeFluxSocketCapturingRequest(
"HTTP/1.1 200 OK\r\n".
"Content-Type: application/json\r\n".
'Content-Length: '.strlen($body)."\r\n".
"\r\n".
$body,
$requestPath,
fn () => (new FluxClient)->listContainers('100.64.0.10')
);
$request = file_get_contents($requestPath) ?: '';
@unlink($requestPath);
expect($request)->toContain('"type":"containers.list"')
->not->toContain('list_containers');
});
function withFakeFluxSocketCapturingRequest(string $response, string $requestPath, Closure $callback): void
{
$directory = storage_path('framework/testing');
if (! is_dir($directory)) {
mkdir($directory, 0777, true);
}
$socketPath = $directory.'/flux-'.bin2hex(random_bytes(8)).'.sock';
$server = stream_socket_server("unix://{$socketPath}", $errorCode, $errorMessage);
expect($server)->not->toBeFalse("Could not create fake Flux socket: {$errorMessage} ({$errorCode})");
$pid = pcntl_fork();
if ($pid === 0) {
$connection = stream_socket_accept($server, 5);
if ($connection !== false) {
$request = '';
while (! str_contains($request, "\r\n\r\n") && ! feof($connection)) {
$request .= fread($connection, 8192);
}
if (preg_match('/Content-Length: (\d+)/i', $request, $matches) === 1) {
$remaining = (int) $matches[1] - strlen(substr($request, strpos($request, "\r\n\r\n") + 4));
while ($remaining > 0 && ! feof($connection)) {
$chunk = fread($connection, $remaining);
$request .= $chunk;
$remaining -= strlen($chunk);
}
}
file_put_contents($requestPath, $request);
fwrite($connection, $response);
fclose($connection);
}
fclose($server);
exit(0);
}
fclose($server);
try {
config(['flux.unix_socket_path' => $socketPath]);
$callback();
pcntl_waitpid($pid, $status);
} finally {
@unlink($socketPath);
}
}