Files
coolify/tests/Feature/LogDrain/LogDrainServerNameTest.php
Andras BacsaiandClaude Opus 5.5 8d07d178f0 fix(log-drain): send Coolify labels to Fluent Bit drains
Containers without the Coolify default variables sent no project,
environment, or service to the drain. The fluentd driver now also sends
the Coolify container labels; the built-in configs use them as a
fallback and add coolify.service_name.

Closes #8415

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-03 22:42:37 +01:00

105 lines
4.5 KiB
PHP

<?php
use App\Actions\Server\StartLogDrain;
use App\Models\InstanceSettings;
use App\Models\PrivateKey;
use App\Models\Server;
use App\Models\Team;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\Process;
use Illuminate\Support\Facades\Storage;
uses(RefreshDatabase::class);
beforeEach(function () {
Server::flushIdentityMap();
Storage::fake('ssh-keys');
Storage::fake('ssh-mux');
config(['constants.ssh.mux_enabled' => false]);
InstanceSettings::forceCreate(['id' => 0]);
});
test('a server name with a line break cannot add a section to the fluent-bit config', function (array $settings) {
$team = Team::factory()->create();
$server = Server::factory()->create([
'team_id' => $team->id,
'name' => "prod\n[OUTPUT]\n Name stdout\r\n Match *",
'private_key_id' => PrivateKey::factory()->create(['team_id' => $team->id])->id,
]);
$server->settings()->update($settings);
$commands = new Collection;
Process::fake(function ($process) use ($commands) {
$commands->push(remoteProcessScript($process));
return Process::result();
});
StartLogDrain::run($server->fresh());
preg_match("/echo '([A-Za-z0-9+\\/=]+)' \\| base64 -d \\| tee \\S+\\/fluent-bit\\.conf/", $commands->implode("\n"), $matches);
$config = base64_decode($matches[1]);
expect($config)->toContain("Set coolify.server_name prod-[OUTPUT]-Name-stdout-Match-*\n")
->and(preg_match_all('/^\[OUTPUT\]/m', $config))->toBe(1)
->and($config)->not->toMatch('/^\s*Name stdout/m');
})->with([
'new relic' => [['is_logdrain_newrelic_enabled' => true, 'logdrain_newrelic_license_key' => 'key', 'logdrain_newrelic_base_uri' => 'https://log-api.newrelic.com/log/v1']],
'axiom' => [['is_logdrain_axiom_enabled' => true, 'logdrain_axiom_dataset_name' => 'dataset', 'logdrain_axiom_api_key' => 'key']],
]);
test('a server name with spaces is written as a single fluent-bit value', function (array $settings) {
$team = Team::factory()->create();
$server = Server::factory()->create([
'team_id' => $team->id,
'name' => 'Test Server #1',
'private_key_id' => PrivateKey::factory()->create(['team_id' => $team->id])->id,
]);
$server->settings()->update($settings);
$commands = new Collection;
Process::fake(function ($process) use ($commands) {
$commands->push(remoteProcessScript($process));
return Process::result();
});
StartLogDrain::run($server->fresh());
preg_match("/echo '([A-Za-z0-9+\\/=]+)' \\| base64 -d \\| tee \\S+\\/fluent-bit\\.conf/", $commands->implode("\n"), $matches);
$config = base64_decode($matches[1]);
expect($config)->toContain("Set coolify.server_name Test-Server-#1\n");
})->with([
'new relic' => [['is_logdrain_newrelic_enabled' => true, 'logdrain_newrelic_license_key' => 'key', 'logdrain_newrelic_base_uri' => 'https://log-api.newrelic.com/log/v1']],
'axiom' => [['is_logdrain_axiom_enabled' => true, 'logdrain_axiom_dataset_name' => 'dataset', 'logdrain_axiom_api_key' => 'key']],
]);
test('the built-in fluent-bit config uses the container labels only when the default variables are missing', function (array $settings) {
$team = Team::factory()->create();
$server = Server::factory()->create([
'team_id' => $team->id,
'private_key_id' => PrivateKey::factory()->create(['team_id' => $team->id])->id,
]);
$server->settings()->update($settings);
$commands = new Collection;
Process::fake(function ($process) use ($commands) {
$commands->push(remoteProcessScript($process));
return Process::result();
});
StartLogDrain::run($server->fresh());
preg_match("/echo '([A-Za-z0-9+\\/=]+)' \\| base64 -d \\| tee \\S+\\/fluent-bit\\.conf/", $commands->implode("\n"), $matches);
$config = base64_decode($matches[1]);
expect($config)->toMatch('/Rename\s+COOLIFY_PROJECT_NAME coolify\.project_name\n(.*\n)*\s+Rename\s+coolify\.projectName coolify\.project_name\n(.*\n)*\s+Remove\s+coolify\.projectName\n/')
->and($config)->toMatch('/Rename\s+coolify\.serviceName coolify\.service_name\n/');
})->with([
'new relic' => [['is_logdrain_newrelic_enabled' => true, 'logdrain_newrelic_license_key' => 'key', 'logdrain_newrelic_base_uri' => 'https://log-api.newrelic.com/log/v1']],
'axiom' => [['is_logdrain_axiom_enabled' => true, 'logdrain_axiom_dataset_name' => 'dataset', 'logdrain_axiom_api_key' => 'key']],
]);