Remove networks on compose down
Release rolling / release (push) Has been cancelled

This commit is contained in:
Raven Scott
2026-07-16 04:40:50 -04:00
parent 2c35f5cb82
commit 67dffcadb8
2 changed files with 169 additions and 4 deletions
+102
View File
@@ -2,8 +2,44 @@ import test from 'brittle'
import {
parseComposeFile,
validateComposeFile,
removeComposeStack,
} from '../server/utils/composeManager.js'
/**
* Minimal dockerode-shaped mock for removeComposeStack.
* @param {{ containers?: object[], networks?: object[] }} seed
*/
function mockDocker(seed = {}) {
const containers = [...(seed.containers || [])]
const networks = [...(seed.networks || [])]
const removedNetworks = []
const removedContainers = []
return {
removedNetworks,
removedContainers,
listContainers: async () => containers,
listNetworks: async () => networks,
getContainer: (id) => ({
stop: async () => {},
remove: async () => {
removedContainers.push(id)
const i = containers.findIndex((c) => c.Id === id)
if (i >= 0) containers.splice(i, 1)
},
}),
getNetwork: (id) => ({
remove: async () => {
const n = networks.find((x) => x.Id === id)
if (!n) throw new Error(`network ${id} not found`)
removedNetworks.push({ id, name: n.Name })
const i = networks.findIndex((x) => x.Id === id)
if (i >= 0) networks.splice(i, 1)
},
}),
}
}
const SAMPLE = `
version: "3.8"
services:
@@ -84,3 +120,69 @@ services:
`)
t.ok(parsed.services.app.build)
})
test('removeComposeStack removes project networks after containers', async (t) => {
const docker = mockDocker({
containers: [
{
Id: 'c1',
State: 'running',
Labels: { 'com.docker.compose.project': 'mystack' },
},
],
networks: [
{
Id: 'n1',
Name: 'mystack_default',
Labels: { 'com.docker.compose.project': 'mystack' },
},
{
Id: 'n2',
Name: 'other_default',
Labels: { 'com.docker.compose.project': 'other' },
},
{
Id: 'bridge',
Name: 'bridge',
Labels: {},
},
],
})
const result = await removeComposeStack(docker, 'mystack')
t.is(result.removed, 1)
t.is(result.networksRemoved, 1)
t.alike(docker.removedContainers, ['c1'])
t.is(docker.removedNetworks.length, 1)
t.is(docker.removedNetworks[0].name, 'mystack_default')
})
test('removeComposeStack cleans orphaned project networks with no containers', async (t) => {
const docker = mockDocker({
containers: [],
networks: [
{
Id: 'n1',
Name: 'orphan_backend',
Labels: { 'com.docker.compose.project': 'orphan' },
},
],
})
const result = await removeComposeStack(docker, 'orphan')
t.is(result.removed, 0)
t.is(result.networksRemoved, 1)
t.is(docker.removedNetworks[0].name, 'orphan_backend')
})
test('removeComposeStack reports already removed when nothing matches', async (t) => {
const docker = mockDocker({
containers: [],
networks: [{ Id: 'bridge', Name: 'bridge', Labels: {} }],
})
const result = await removeComposeStack(docker, 'missing')
t.is(result.removed, 0)
t.is(result.networksRemoved, 0)
t.ok(/not found|already removed/i.test(result.message))
})