This commit is contained in:
@@ -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))
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user