From f31abca31896f77e53a1a686f5363dcc70df94eb Mon Sep 17 00:00:00 2001 From: oniani1 Date: Thu, 30 Apr 2026 00:23:56 +0400 Subject: [PATCH 1/2] fix: allow PUT tenant to clear database_pool_url --- src/http/routes/admin/tenants.ts | 4 ++-- src/test/tenant.test.ts | 31 +++++++++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/http/routes/admin/tenants.ts b/src/http/routes/admin/tenants.ts index 503d543be..ece965927 100644 --- a/src/http/routes/admin/tenants.ts +++ b/src/http/routes/admin/tenants.ts @@ -624,8 +624,8 @@ export default async function routes(fastify: FastifyInstance) { tenantInfo.feature_s3_protocol = features?.s3Protocol?.enabled } - if (databasePoolUrl) { - tenantInfo.database_pool_url = encrypt(databasePoolUrl) + if (databasePoolUrl !== undefined) { + tenantInfo.database_pool_url = databasePoolUrl === null ? null : encrypt(databasePoolUrl) } if (maxConnections) { diff --git a/src/test/tenant.test.ts b/src/test/tenant.test.ts index 861bfccff..b08915dc2 100644 --- a/src/test/tenant.test.ts +++ b/src/test/tenant.test.ts @@ -819,6 +819,37 @@ describe('Tenant configs', () => { expect(getResponseJSON.databasePoolUrl).toBeNull() }) + test('PUT clears tenant databasePoolUrl when set to null', async () => { + await adminApp.inject({ + method: 'POST', + url: `/tenants/abc`, + payload, + headers: { + apikey: process.env.ADMIN_API_KEYS, + }, + }) + + const putResponse = await adminApp.inject({ + method: 'PUT', + url: `/tenants/abc`, + payload: { ...payload, databasePoolUrl: null }, + headers: { + apikey: process.env.ADMIN_API_KEYS, + }, + }) + expect(putResponse.statusCode).toBe(204) + + const getResponse = await adminApp.inject({ + method: 'GET', + url: `/tenants/abc`, + headers: { + apikey: process.env.ADMIN_API_KEYS, + }, + }) + expect(getResponse.statusCode).toBe(200) + expect(JSON.parse(getResponse.body).databasePoolUrl).toBeNull() + }) + test('Upsert tenant config updates iceberg/vector limits when enabled is omitted', async () => { await adminApp.inject({ method: 'POST', From 94d4ffa7729160cb81dc7758366505b355800b76 Mon Sep 17 00:00:00 2001 From: ferhat elmas Date: Wed, 15 Jul 2026 10:15:56 +0200 Subject: [PATCH 2/2] chore: pool mode test as well Signed-off-by: ferhat elmas --- acceptance/specs/admin.test.ts | 5 ----- src/test/tenant.test.ts | 25 ------------------------- 2 files changed, 30 deletions(-) diff --git a/acceptance/specs/admin.test.ts b/acceptance/specs/admin.test.ts index d0a7136b4..8fbd246e9 100644 --- a/acceptance/specs/admin.test.ts +++ b/acceptance/specs/admin.test.ts @@ -36,7 +36,6 @@ interface TenantFeatures { interface TenantDetailResponse { anonKey?: string capabilities?: Record - databasePoolMode?: string | null databasePoolUrl?: string | null databaseUrl?: string fileSizeLimit?: number @@ -574,10 +573,6 @@ function buildTenantProvisionBody( serviceKey: requireString(sourceTenant?.serviceKey, 'serviceKey'), } - if (typeof sourceTenant?.databasePoolMode === 'string') { - body.databasePoolMode = sourceTenant.databasePoolMode - } - if (typeof sourceTenant?.databasePoolUrl === 'string') { body.databasePoolUrl = sourceTenant.databasePoolUrl } diff --git a/src/test/tenant.test.ts b/src/test/tenant.test.ts index b08915dc2..a1f9b6f85 100644 --- a/src/test/tenant.test.ts +++ b/src/test/tenant.test.ts @@ -298,31 +298,6 @@ describe('Tenant configs', () => { await expect(getFeatures('abc')).resolves.toEqual(payload.features) }) - test('Ignores legacy database pool mode fields on tenant writes', async () => { - const response = await adminApp.inject({ - method: 'POST', - url: `/tenants/abc`, - payload: { - ...payload, - databasePoolMode: 'single_use', - }, - headers: { - apikey: process.env.ADMIN_API_KEYS, - }, - }) - expect(response.statusCode).toBe(201) - - const getResponse = await adminApp.inject({ - method: 'GET', - url: `/tenants/abc`, - headers: { - apikey: process.env.ADMIN_API_KEYS, - }, - }) - expect(getResponse.statusCode).toBe(200) - expect(JSON.parse(getResponse.body)).toEqual(payload) - }) - test('PATCH refreshes local tenant config changes before the notify cache path', async () => { const createResponse = await adminApp.inject({ method: 'POST',