Files
peardata/test/container-names.test.js
T
Raven Scott 926a89878b
CI / test (push) Successful in 1m31s
Release rolling / release (push) Successful in 7m10s
Docker Socket Updates attempts (Bare Safe)
2026-07-19 13:38:48 -04:00

128 lines
3.5 KiB
JavaScript

import test from 'brittle'
import {
pickContainerDisplayName,
resolveContainerLabel,
extractContainerIdFromCgroupName,
metricCardSubtitle,
chartOptionLabel,
isHexId,
} from '../shared/container-names.js'
import {
mapDockerContainerNames,
parseHttpBody,
parseDockerPsNames,
} from '../server/services/collectors/docker.js'
import { makeDockerCpuChart, makeDockerMemChart } from '../shared/metrics.js'
test('pickContainerDisplayName prefers compose service', (t) => {
t.is(
pickContainerDisplayName({
Id: 'a'.repeat(64),
Names: ['/myproj_web_1'],
Labels: {
'com.docker.compose.project': 'myproj',
'com.docker.compose.service': 'web',
'com.docker.compose.container-number': '1',
},
}),
'web'
)
t.is(
pickContainerDisplayName({
Id: 'b'.repeat(64),
Names: ['/myproj_web_2'],
Labels: {
'com.docker.compose.service': 'web',
'com.docker.compose.container-number': '2',
},
}),
'web · 2'
)
})
test('pickContainerDisplayName falls back to Names then image', (t) => {
t.is(
pickContainerDisplayName({
Id: 'c'.repeat(64),
Names: ['/friendly-name'],
Labels: {},
}),
'friendly-name'
)
t.is(
pickContainerDisplayName({
Id: 'd'.repeat(64),
Names: [],
Image: 'ghcr.io/org/redis:7',
}),
'redis'
)
})
test('mapDockerContainerNames indexes full and short ids', (t) => {
const id = 'abcdef0123456789' + '0'.repeat(48)
const map = mapDockerContainerNames([
{
Id: id,
Names: ['/nginx'],
Labels: {},
},
])
t.is(map.get(id), 'nginx')
t.is(map.get(id.slice(0, 12)), 'nginx')
})
test('parseHttpBody handles Content-Length and chunked Docker replies', (t) => {
const json = '[{"Id":"aa","Names":["/x"]}]'
const plain =
`HTTP/1.1 200 OK\r\nContent-Type: application/json\r\nContent-Length: ${json.length}\r\n\r\n` +
json
t.is(parseHttpBody(plain), json)
const chunked =
'HTTP/1.1 200 OK\r\nTransfer-Encoding: chunked\r\n\r\n' +
Number(json.length).toString(16) +
'\r\n' +
json +
'\r\n0\r\n\r\n'
t.is(parseHttpBody(chunked), json)
})
test('parseDockerPsNames maps id to Names', (t) => {
const id = '45b3a7631c68aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa'
const map = parseDockerPsNames(`${id}\tdozzle\n`)
t.is(map.get(id.slice(0, 12)), 'dozzle')
t.is(map.get('dozzle'), 'dozzle')
})
test('resolveContainerLabel humanizes cgroup docker scopes', (t) => {
const id = 'a1b2c3d4e5f6789012345678abcdef01'
const map = new Map([
[id, 'api'],
[id.slice(0, 12), 'api'],
])
t.is(resolveContainerLabel(`docker-${id}.scope`, map), 'api')
t.is(resolveContainerLabel(id, map), 'api')
t.is(resolveContainerLabel(`docker-${id}`, new Map()), `container ${id.slice(0, 12)}`)
t.ok(extractContainerIdFromCgroupName(`docker-${id}.scope`)?.startsWith('a1b2'))
})
test('docker chart titles use display names', (t) => {
const cpu = makeDockerCpuChart('abc123def456', 'nginx')
t.is(cpu.title, 'nginx · CPU')
t.is(cpu.family, 'nginx')
const mem = makeDockerMemChart('abc123def456', 'nginx')
t.is(mem.title, 'nginx · memory')
})
test('metricCardSubtitle hides hashes for container charts', (t) => {
const id = 'docker.cpu.abc123def456'
t.is(
metricCardSubtitle(id, { title: 'nginx · CPU', family: 'nginx', units: 'percentage' }),
'percentage'
)
t.absent(metricCardSubtitle(id, { units: 'percentage' }).includes('abc123'))
t.ok(isHexId('abc123def456'))
t.is(chartOptionLabel(id, { title: 'nginx · CPU' }), 'nginx · CPU')
})