also looking at this
feat(fleet): refuse to destroy a server still holding a moved site's rollback
#182
4 files
+284
-2
| @@ -24,6 +24,7 @@ import { afterAll, beforeAll, describe, expect, it } from 'bun:test' | ||
| 24 | 24 | import { mkdtemp, rm, writeFile } from 'node:fs/promises' |
| 25 | 25 | import { tmpdir } from 'node:os' |
| 26 | 26 | import { join } from 'node:path' |
| 27 | import { buildDrainedSiteScanScript, parseDrainedSites } from '../../src/operations/drained-sites' | |
| 27 | 28 | import { |
| 28 | 29 | buildCertificatePackScript, |
| 29 | 30 | buildCertificateStateScript, |
| @@ -318,10 +319,32 @@ describe.skipIf(!canRun)('site:move between two boxes (docker)', () => { | ||
| 318 | 319 | expect((await exec(SOURCE, `test -f /etc/systemd/system/${SLUG}-${SITE}.service`)).code).toBe(0) |
| 319 | 320 | }) |
| 320 | 321 | |
| 322 | /** | |
| 323 | * The drained tree is the rollback, and a teardown would take it. The scan has | |
| 324 | * to see that on a real box: the site's files present, nothing running for it. | |
| 325 | */ | |
| 326 | it('is reported as a drained site, so a teardown can refuse', async () => { | |
| 327 | const scan = await run(SOURCE, buildDrainedSiteScanScript(SLUG).join('\n')) | |
| 328 | const drained = parseDrainedSites(scan) | |
| 329 | expect(drained.map(site => site.name)).toContain(SITE) | |
| 330 | expect(drained[0].size).not.toBe('?') | |
| 331 | }) | |
| 332 | ||
| 333 | it('is not reported as drained on the target, which is serving it', async () => { | |
| 334 | const scan = await run(TARGET, buildDrainedSiteScanScript(SLUG).join('\n')) | |
| 335 | expect(parseDrainedSites(scan)).toEqual([]) | |
| 336 | }) | |
| 337 | ||
| 321 | 338 | it('comes back on the source by restarting it, with its data intact', async () => { |
| 322 | 339 | await run(SOURCE, `systemctl start ${SLUG}-${SITE}.service`) |
| 323 | 340 | const health = await exec(SOURCE, buildHealthGateScript(PORT, '/')) |
| 324 | 341 | expect(health.code).toBe(0) |
| 325 | 342 | expect((await run(SOURCE, `cat ${APP_BASE}/shared/database/app.sqlite`)).trim()).toBe(SHARED_DB_CONTENT) |
| 326 | 343 | }) |
| 344 | ||
| 345 | /** Once the source is serving again, it is no longer holding anyone's rollback. */ | |
| 346 | it('stops being reported as drained once it serves again', async () => { | |
| 347 | const scan = await run(SOURCE, buildDrainedSiteScanScript(SLUG).join('\n')) | |
| 348 | expect(parseDrainedSites(scan)).toEqual([]) | |
| 349 | }) | |
| 327 | 350 | }) |