mirror of
https://github.com/coollabsio/coolify.git
synced 2025-12-28 05:34:50 +00:00
Refactor: Centralize service application prerequisites
Refactors the Appwrite and Beszel service-specific application settings to use a centralized constant-based approach, following the same pattern as NEEDS_TO_CONNECT_TO_PREDEFINED_NETWORK. Changes: - Added NEEDS_TO_DISABLE_GZIP constant for services requiring gzip disabled - Added NEEDS_TO_DISABLE_STRIPPREFIX constant for services requiring stripprefix disabled - Created applyServiceApplicationPrerequisites() helper function in bootstrap/helpers/services.php - Updated all service creation flows to use the centralized helper: * app/Livewire/Project/Resource/Create.php (web handler) * app/Http/Controllers/Api/ServicesController.php (API handler - BUG FIX) * app/Livewire/Project/New/DockerCompose.php (custom compose handler) * app/Http/Controllers/Api/ApplicationsController.php (API custom compose handler) - Added comprehensive unit tests for the new helper function Benefits: - Single source of truth for service prerequisites - DRY - eliminates code duplication between web and API handlers - Fixes bug where API-created services didn't get prerequisites applied - Easy to extend for future services (just edit the constant) - More maintainable and testable Related commits:3a94f1ea1(Beszel),02b18c86e(Appwrite) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
b246cdffab
commit
4706bc23aa
@ -1652,6 +1652,10 @@ class ApplicationsController extends Controller
|
||||
$service->save();
|
||||
|
||||
$service->parse(isNew: true);
|
||||
|
||||
// Apply service-specific application prerequisites
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
if ($instantDeploy) {
|
||||
StartService::dispatch($service);
|
||||
}
|
||||
|
||||
@ -376,6 +376,10 @@ class ServicesController extends Controller
|
||||
});
|
||||
}
|
||||
$service->parse(isNew: true);
|
||||
|
||||
// Apply service-specific application prerequisites
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
if ($instantDeploy) {
|
||||
StartService::dispatch($service);
|
||||
}
|
||||
|
||||
@ -74,6 +74,9 @@ class DockerCompose extends Component
|
||||
}
|
||||
$service->parse(isNew: true);
|
||||
|
||||
// Apply service-specific application prerequisites
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
return redirect()->route('project.service.configuration', [
|
||||
'service_uuid' => $service->uuid,
|
||||
'environment_uuid' => $environment->uuid,
|
||||
|
||||
@ -104,25 +104,8 @@ class Create extends Component
|
||||
}
|
||||
$service->parse(isNew: true);
|
||||
|
||||
// For Beszel service disable gzip (fixes realtime not working issue)
|
||||
if ($oneClickServiceName === 'beszel') {
|
||||
$appService = $service->applications()->whereName('beszel')->first();
|
||||
if ($appService) {
|
||||
$appService->is_gzip_enabled = false;
|
||||
$appService->save();
|
||||
}
|
||||
}
|
||||
// For Appwrite services, disable strip prefix for services that handle domain requests
|
||||
if ($oneClickServiceName === 'appwrite') {
|
||||
$servicesToDisableStripPrefix = ['appwrite', 'appwrite-console', 'appwrite-realtime'];
|
||||
foreach ($servicesToDisableStripPrefix as $serviceName) {
|
||||
$appService = $service->applications()->whereName($serviceName)->first();
|
||||
if ($appService) {
|
||||
$appService->is_stripprefix_enabled = false;
|
||||
$appService->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
// Apply service-specific application prerequisites
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
return redirect()->route('project.service.configuration', [
|
||||
'service_uuid' => $service->uuid,
|
||||
|
||||
@ -71,4 +71,10 @@ const NEEDS_TO_CONNECT_TO_PREDEFINED_NETWORK = [
|
||||
'pgadmin',
|
||||
'postgresus',
|
||||
];
|
||||
const NEEDS_TO_DISABLE_GZIP = [
|
||||
'beszel' => ['beszel'],
|
||||
];
|
||||
const NEEDS_TO_DISABLE_STRIPPREFIX = [
|
||||
'appwrite' => ['appwrite', 'appwrite-console', 'appwrite-realtime'],
|
||||
];
|
||||
const SHARED_VARIABLE_TYPES = ['team', 'project', 'environment'];
|
||||
|
||||
@ -339,3 +339,55 @@ function parseServiceEnvironmentVariable(string $key): array
|
||||
'has_port' => $hasPort,
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply service-specific application prerequisites after service parse.
|
||||
*
|
||||
* This function configures application-level settings that are required for
|
||||
* specific one-click services to work correctly (e.g., disabling gzip for Beszel,
|
||||
* disabling strip prefix for Appwrite services).
|
||||
*
|
||||
* Must be called AFTER $service->parse() since it requires applications to exist.
|
||||
*
|
||||
* @param Service $service The service to apply prerequisites to
|
||||
* @return void
|
||||
*/
|
||||
function applyServiceApplicationPrerequisites(Service $service): void
|
||||
{
|
||||
try {
|
||||
// Extract service name from service name (format: "servicename-uuid")
|
||||
$serviceName = str($service->name)->before('-')->value();
|
||||
|
||||
// Apply gzip disabling if needed
|
||||
if (array_key_exists($serviceName, NEEDS_TO_DISABLE_GZIP)) {
|
||||
$applicationNames = NEEDS_TO_DISABLE_GZIP[$serviceName];
|
||||
foreach ($applicationNames as $applicationName) {
|
||||
$application = $service->applications()->whereName($applicationName)->first();
|
||||
if ($application) {
|
||||
$application->is_gzip_enabled = false;
|
||||
$application->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Apply stripprefix disabling if needed
|
||||
if (array_key_exists($serviceName, NEEDS_TO_DISABLE_STRIPPREFIX)) {
|
||||
$applicationNames = NEEDS_TO_DISABLE_STRIPPREFIX[$serviceName];
|
||||
foreach ($applicationNames as $applicationName) {
|
||||
$application = $service->applications()->whereName($applicationName)->first();
|
||||
if ($application) {
|
||||
$application->is_stripprefix_enabled = false;
|
||||
$application->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
// Log error but don't throw - prerequisites are nice-to-have, not critical
|
||||
Log::error('Failed to apply service application prerequisites', [
|
||||
'service_id' => $service->id,
|
||||
'service_name' => $service->name,
|
||||
'error' => $e->getMessage(),
|
||||
'trace' => $e->getTraceAsString(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
103
tests/Unit/ServiceApplicationPrerequisitesTest.php
Normal file
103
tests/Unit/ServiceApplicationPrerequisitesTest.php
Normal file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Service;
|
||||
use App\Models\ServiceApplication;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
it('applies beszel gzip prerequisite correctly', function () {
|
||||
$application = Mockery::mock(ServiceApplication::class);
|
||||
$application->shouldReceive('save')->once();
|
||||
$application->is_gzip_enabled = true; // Start as enabled
|
||||
|
||||
$query = Mockery::mock();
|
||||
$query->shouldReceive('whereName')
|
||||
->with('beszel')
|
||||
->once()
|
||||
->andReturnSelf();
|
||||
$query->shouldReceive('first')
|
||||
->once()
|
||||
->andReturn($application);
|
||||
|
||||
$service = Mockery::mock(Service::class);
|
||||
$service->name = 'beszel-test-uuid';
|
||||
$service->id = 1;
|
||||
$service->shouldReceive('applications')
|
||||
->once()
|
||||
->andReturn($query);
|
||||
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
expect($application->is_gzip_enabled)->toBeFalse();
|
||||
});
|
||||
|
||||
it('applies appwrite stripprefix prerequisite correctly', function () {
|
||||
$applications = [];
|
||||
|
||||
foreach (['appwrite', 'appwrite-console', 'appwrite-realtime'] as $name) {
|
||||
$app = Mockery::mock(ServiceApplication::class);
|
||||
$app->is_stripprefix_enabled = true; // Start as enabled
|
||||
$app->shouldReceive('save')->once();
|
||||
$applications[$name] = $app;
|
||||
}
|
||||
|
||||
$service = Mockery::mock(Service::class);
|
||||
$service->name = 'appwrite-test-uuid';
|
||||
$service->id = 1;
|
||||
|
||||
$service->shouldReceive('applications')->times(3)->andReturnUsing(function () use (&$applications) {
|
||||
static $callCount = 0;
|
||||
$names = ['appwrite', 'appwrite-console', 'appwrite-realtime'];
|
||||
$currentName = $names[$callCount++];
|
||||
|
||||
$query = Mockery::mock();
|
||||
$query->shouldReceive('whereName')
|
||||
->with($currentName)
|
||||
->once()
|
||||
->andReturnSelf();
|
||||
$query->shouldReceive('first')
|
||||
->once()
|
||||
->andReturn($applications[$currentName]);
|
||||
|
||||
return $query;
|
||||
});
|
||||
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
foreach ($applications as $app) {
|
||||
expect($app->is_stripprefix_enabled)->toBeFalse();
|
||||
}
|
||||
});
|
||||
|
||||
it('handles missing applications gracefully', function () {
|
||||
$query = Mockery::mock();
|
||||
$query->shouldReceive('whereName')
|
||||
->with('beszel')
|
||||
->once()
|
||||
->andReturnSelf();
|
||||
$query->shouldReceive('first')
|
||||
->once()
|
||||
->andReturn(null);
|
||||
|
||||
$service = Mockery::mock(Service::class);
|
||||
$service->name = 'beszel-test-uuid';
|
||||
$service->id = 1;
|
||||
$service->shouldReceive('applications')
|
||||
->once()
|
||||
->andReturn($query);
|
||||
|
||||
// Should not throw exception
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
|
||||
it('skips services without prerequisites', function () {
|
||||
$service = Mockery::mock(Service::class);
|
||||
$service->name = 'unknown-service-uuid';
|
||||
$service->id = 1;
|
||||
$service->shouldNotReceive('applications');
|
||||
|
||||
applyServiceApplicationPrerequisites($service);
|
||||
|
||||
expect(true)->toBeTrue();
|
||||
});
|
||||
Loading…
Reference in New Issue
Block a user