mirror of
https://github.com/coollabsio/coolify.git
synced 2026-11-06 13:10:37 -04:00
fix(api): accept numeric resource limits when creating databases
This commit is contained in:
@@ -139,6 +139,19 @@ class DatabasesController extends Controller
|
||||
return $storage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store numeric resource limits (e.g. 0 or 1.5) as the strings the string limit columns expect.
|
||||
*/
|
||||
private function normalizeNumericLimits(Request $request): void
|
||||
{
|
||||
foreach (['limits_memory', 'limits_memory_swap', 'limits_memory_reservation', 'limits_cpus', 'limits_cpuset'] as $field) {
|
||||
$value = $request->input($field);
|
||||
if (is_int($value) || is_float($value)) {
|
||||
$request->offsetSet($field, (string) $value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function removeSensitiveData($database, bool $loadNestedServerSecrets = false)
|
||||
{
|
||||
$database->makeHidden([
|
||||
@@ -2023,6 +2036,7 @@ class DatabasesController extends Controller
|
||||
return response()->json(['message' => 'Public port already used by another database.'], 400);
|
||||
}
|
||||
}
|
||||
$this->normalizeNumericLimits($request);
|
||||
$validator = customApiValidator($request->all(), [
|
||||
'name' => 'string|max:255',
|
||||
'description' => 'string|nullable',
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
use App\Models\Environment;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Project;
|
||||
use App\Models\Server;
|
||||
use App\Models\StandalonePostgresql;
|
||||
use App\Models\Team;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
use Illuminate\Support\Facades\Queue;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
beforeEach(function () {
|
||||
config(['app.maintenance.driver' => 'file']);
|
||||
InstanceSettings::unguarded(fn () => InstanceSettings::firstOrCreate(['id' => 0], ['is_api_enabled' => true]));
|
||||
Server::flushIdentityMap();
|
||||
|
||||
$this->team = Team::factory()->create();
|
||||
$this->user = User::factory()->create();
|
||||
$this->team->members()->attach($this->user->id, ['role' => 'owner']);
|
||||
session(['currentTeam' => $this->team]);
|
||||
|
||||
$this->server = Server::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->project = Project::factory()->create(['team_id' => $this->team->id]);
|
||||
$this->environment = Environment::factory()->create(['project_id' => $this->project->id]);
|
||||
|
||||
Queue::fake();
|
||||
});
|
||||
|
||||
function databaseCreateNumericLimitsHeaders(User $user, int $teamId): array
|
||||
{
|
||||
$plainTextToken = Str::random(40);
|
||||
$token = $user->tokens()->create([
|
||||
'name' => 'database-create-numeric-limits-test',
|
||||
'token' => hash('sha256', $plainTextToken),
|
||||
'abilities' => ['write'],
|
||||
'team_id' => $teamId,
|
||||
]);
|
||||
|
||||
return ['Authorization' => 'Bearer '.$token->getKey().'|'.$plainTextToken];
|
||||
}
|
||||
|
||||
function databaseCreateNumericLimitsPayload(object $test, array $overrides = []): array
|
||||
{
|
||||
return array_merge([
|
||||
'project_uuid' => $test->project->uuid,
|
||||
'environment_uuid' => $test->environment->uuid,
|
||||
'server_uuid' => $test->server->uuid,
|
||||
], $overrides);
|
||||
}
|
||||
|
||||
test('numeric resource limits are accepted and stored as strings', function (string $type) {
|
||||
$response = $this->withHeaders(databaseCreateNumericLimitsHeaders($this->user, $this->team->id))
|
||||
->postJson("/api/v1/databases/{$type}", databaseCreateNumericLimitsPayload($this, [
|
||||
'limits_memory' => 0,
|
||||
'limits_memory_swap' => 1024,
|
||||
'limits_memory_reservation' => 512,
|
||||
'limits_cpus' => 1.5,
|
||||
'limits_cpuset' => 1,
|
||||
]))
|
||||
->assertCreated();
|
||||
|
||||
$database = queryDatabaseByUuidWithinTeam($response->json('uuid'), $this->team->id);
|
||||
|
||||
expect($database->limits_memory)->toBe('0')
|
||||
->and($database->limits_memory_swap)->toBe('1024')
|
||||
->and($database->limits_memory_reservation)->toBe('512')
|
||||
->and($database->limits_cpus)->toBe('1.5')
|
||||
->and($database->limits_cpuset)->toBe('1');
|
||||
})->with(['postgresql', 'mysql', 'mariadb', 'mongodb', 'redis', 'keydb', 'dragonfly', 'clickhouse', 'sqlite']);
|
||||
|
||||
test('string resource limits are still accepted', function () {
|
||||
$response = $this->withHeaders(databaseCreateNumericLimitsHeaders($this->user, $this->team->id))
|
||||
->postJson('/api/v1/databases/postgresql', databaseCreateNumericLimitsPayload($this, [
|
||||
'limits_memory' => '512m',
|
||||
'limits_cpus' => '0.5',
|
||||
]))
|
||||
->assertCreated();
|
||||
|
||||
$database = queryDatabaseByUuidWithinTeam($response->json('uuid'), $this->team->id);
|
||||
|
||||
expect($database->limits_memory)->toBe('512m')
|
||||
->and($database->limits_cpus)->toBe('0.5');
|
||||
});
|
||||
|
||||
test('non-scalar or boolean resource limits are rejected', function (string $field, mixed $value) {
|
||||
$this->withHeaders(databaseCreateNumericLimitsHeaders($this->user, $this->team->id))
|
||||
->postJson('/api/v1/databases/postgresql', databaseCreateNumericLimitsPayload($this, [$field => $value]))
|
||||
->assertUnprocessable()
|
||||
->assertJsonValidationErrors($field);
|
||||
|
||||
expect(StandalonePostgresql::count())->toBe(0);
|
||||
})->with([
|
||||
'array memory' => ['limits_memory', ['512m']],
|
||||
'array cpus' => ['limits_cpus', [1.5]],
|
||||
'boolean cpus' => ['limits_cpus', true],
|
||||
'object memory swap' => ['limits_memory_swap', ['value' => 1]],
|
||||
]);
|
||||
Reference in New Issue
Block a user