mirror of
https://github.com/actions/runner-container-hooks.git
synced 2026-04-03 01:36:16 +08:00
Resolve service name conflicts when the name is computed to the same value
This commit is contained in:
@@ -58,14 +58,30 @@ export async function prepareJob(
|
||||
}
|
||||
|
||||
let services: k8s.V1Container[] = []
|
||||
let serviceNames: string[] = []
|
||||
if (args.services?.length) {
|
||||
const occurrences = new Map<string, number>()
|
||||
for (const s of args.services) {
|
||||
const base = generateContainerName(s.image)
|
||||
occurrences.set(base, (occurrences.get(base) || 0) + 1)
|
||||
}
|
||||
|
||||
const indices = new Map<string, number>()
|
||||
services = args.services.map(service => {
|
||||
return createContainerSpec(
|
||||
service,
|
||||
generateContainerName(service.image),
|
||||
false,
|
||||
extension
|
||||
)
|
||||
const base = generateContainerName(service.image)
|
||||
const total = occurrences.get(base) || 0
|
||||
const idx = indices.get(base) || 0
|
||||
|
||||
let name: string
|
||||
if (total > 1) {
|
||||
name = `${base}-${idx}`
|
||||
} else {
|
||||
name = base
|
||||
}
|
||||
|
||||
indices.set(base, idx + 1)
|
||||
serviceNames.push(name)
|
||||
return createContainerSpec(service, name, false, extension)
|
||||
})
|
||||
}
|
||||
|
||||
@@ -153,14 +169,15 @@ export async function prepareJob(
|
||||
throw new Error(`failed to determine if the pod is alpine: ${message}`)
|
||||
}
|
||||
core.debug(`Setting isAlpine to ${isAlpine}`)
|
||||
generateResponseFile(responseFile, args, createdPod, isAlpine)
|
||||
generateResponseFile(responseFile, args, createdPod, isAlpine, serviceNames)
|
||||
}
|
||||
|
||||
function generateResponseFile(
|
||||
responseFile: string,
|
||||
args: PrepareJobArgs,
|
||||
appPod: k8s.V1Pod,
|
||||
isAlpine: boolean
|
||||
isAlpine: boolean,
|
||||
serviceNames?: string[]
|
||||
): void {
|
||||
if (!appPod.metadata?.name) {
|
||||
throw new Error('app pod must have metadata.name specified')
|
||||
@@ -193,7 +210,9 @@ function generateResponseFile(
|
||||
|
||||
if (args.services?.length) {
|
||||
const serviceContainerNames =
|
||||
args.services?.map(s => generateContainerName(s.image)) || []
|
||||
serviceNames && serviceNames.length
|
||||
? serviceNames
|
||||
: args.services?.map(s => generateContainerName(s.image)) || []
|
||||
|
||||
response.context['services'] = appPod?.spec?.containers
|
||||
?.filter(c => serviceContainerNames.includes(c.name))
|
||||
|
||||
@@ -243,4 +243,29 @@ describe('Prepare job', () => {
|
||||
'ghcr.io/actions/actions-runner:latest'
|
||||
)
|
||||
})
|
||||
|
||||
it('should create unique service container names when images collide', async () => {
|
||||
// make two services with the same image
|
||||
const svc = JSON.parse(JSON.stringify(prepareJobData.args.services[0]))
|
||||
prepareJobData.args.services = [svc, JSON.parse(JSON.stringify(svc))]
|
||||
// ensure registries are null as TestHelper expects
|
||||
prepareJobData.args.services.forEach((s: any) => (s.registry = null))
|
||||
|
||||
await expect(
|
||||
prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
||||
).resolves.not.toThrow()
|
||||
|
||||
const content = JSON.parse(
|
||||
fs.readFileSync(prepareJobOutputFilePath).toString()
|
||||
)
|
||||
|
||||
expect(content.context.services).toBeTruthy()
|
||||
expect(content.context.services.length).toBe(2)
|
||||
|
||||
const got = await getPodByName(content.state.jobPod)
|
||||
const names = (got.spec?.containers || []).map(c => c.name)
|
||||
|
||||
// when images collide, names should be suffixed with -0, -1
|
||||
expect(names).toEqual(expect.arrayContaining(['redis-0', 'redis-1']))
|
||||
})
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user