mirror of
https://github.com/actions/runner-container-hooks.git
synced 2025-12-14 08:36:45 +00:00
fix: naming for services & service entrypoint (#53)
* rename to container * fix container image name bug * fix entrypoint bug * bump patch version * formatting * fix versions in package-lock * add test * revert version bump * added check + test for args as well * formatting * remove cscode launch.json * expand example json * wrong version, revert to correct one * correct lock * throw error on invalid image definition * change falsy check * Update packages/k8s/src/k8s/utils.ts Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com> Co-authored-by: Ferenc Hammerl <31069338+fhammerl@users.noreply.github.com>
This commit is contained in:
@@ -73,6 +73,8 @@
|
|||||||
"contextName": "redis",
|
"contextName": "redis",
|
||||||
"image": "redis",
|
"image": "redis",
|
||||||
"createOptions": "--cpus 1",
|
"createOptions": "--cpus 1",
|
||||||
|
"entrypoint": null,
|
||||||
|
"entryPointArgs": [],
|
||||||
"environmentVariables": {},
|
"environmentVariables": {},
|
||||||
"userMountVolumes": [
|
"userMountVolumes": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import {
|
|||||||
containerVolumes,
|
containerVolumes,
|
||||||
DEFAULT_CONTAINER_ENTRY_POINT,
|
DEFAULT_CONTAINER_ENTRY_POINT,
|
||||||
DEFAULT_CONTAINER_ENTRY_POINT_ARGS,
|
DEFAULT_CONTAINER_ENTRY_POINT_ARGS,
|
||||||
|
generateContainerName,
|
||||||
PodPhase
|
PodPhase
|
||||||
} from '../k8s/utils'
|
} from '../k8s/utils'
|
||||||
import { JOB_CONTAINER_NAME } from './constants'
|
import { JOB_CONTAINER_NAME } from './constants'
|
||||||
@@ -31,14 +32,14 @@ export async function prepareJob(
|
|||||||
let container: k8s.V1Container | undefined = undefined
|
let container: k8s.V1Container | undefined = undefined
|
||||||
if (args.container?.image) {
|
if (args.container?.image) {
|
||||||
core.debug(`Using image '${args.container.image}' for job image`)
|
core.debug(`Using image '${args.container.image}' for job image`)
|
||||||
container = createPodSpec(args.container, JOB_CONTAINER_NAME, true)
|
container = createContainerSpec(args.container, JOB_CONTAINER_NAME, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
let services: k8s.V1Container[] = []
|
let services: k8s.V1Container[] = []
|
||||||
if (args.services?.length) {
|
if (args.services?.length) {
|
||||||
services = args.services.map(service => {
|
services = args.services.map(service => {
|
||||||
core.debug(`Adding service '${service.image}' to pod definition`)
|
core.debug(`Adding service '${service.image}' to pod definition`)
|
||||||
return createPodSpec(service, service.image.split(':')[0])
|
return createContainerSpec(service, generateContainerName(service.image))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
if (!container && !services?.length) {
|
if (!container && !services?.length) {
|
||||||
@@ -153,7 +154,7 @@ async function copyExternalsToRoot(): Promise<void> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPodSpec(
|
export function createContainerSpec(
|
||||||
container,
|
container,
|
||||||
name: string,
|
name: string,
|
||||||
jobContainer = false
|
jobContainer = false
|
||||||
@@ -166,14 +167,20 @@ function createPodSpec(
|
|||||||
const podContainer = {
|
const podContainer = {
|
||||||
name,
|
name,
|
||||||
image: container.image,
|
image: container.image,
|
||||||
command: [container.entryPoint],
|
|
||||||
args: container.entryPointArgs,
|
|
||||||
ports: containerPorts(container)
|
ports: containerPorts(container)
|
||||||
} as k8s.V1Container
|
} as k8s.V1Container
|
||||||
if (container.workingDirectory) {
|
if (container.workingDirectory) {
|
||||||
podContainer.workingDir = container.workingDirectory
|
podContainer.workingDir = container.workingDirectory
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (container.entryPoint) {
|
||||||
|
podContainer.command = [container.entryPoint]
|
||||||
|
}
|
||||||
|
|
||||||
|
if (container.entryPointArgs?.length > 0) {
|
||||||
|
podContainer.args = container.entryPointArgs
|
||||||
|
}
|
||||||
|
|
||||||
podContainer.env = []
|
podContainer.env = []
|
||||||
for (const [key, value] of Object.entries(
|
for (const [key, value] of Object.entries(
|
||||||
container['environmentVariables']
|
container['environmentVariables']
|
||||||
|
|||||||
@@ -137,6 +137,17 @@ exec ${environmentPrefix} ${entryPoint} ${
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function generateContainerName(image: string): string {
|
||||||
|
const nameWithTag = image.split('/').pop()
|
||||||
|
const name = nameWithTag?.split(':').at(0)
|
||||||
|
|
||||||
|
if (!name) {
|
||||||
|
throw new Error(`Image definition '${image}' is invalid`)
|
||||||
|
}
|
||||||
|
|
||||||
|
return name
|
||||||
|
}
|
||||||
|
|
||||||
export enum PodPhase {
|
export enum PodPhase {
|
||||||
PENDING = 'Pending',
|
PENDING = 'Pending',
|
||||||
RUNNING = 'Running',
|
RUNNING = 'Running',
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import { containerPorts, POD_VOLUME_NAME } from '../src/k8s'
|
import { containerPorts, POD_VOLUME_NAME } from '../src/k8s'
|
||||||
import { containerVolumes, writeEntryPointScript } from '../src/k8s/utils'
|
import {
|
||||||
|
containerVolumes,
|
||||||
|
generateContainerName,
|
||||||
|
writeEntryPointScript
|
||||||
|
} from '../src/k8s/utils'
|
||||||
import { TestHelper } from './test-setup'
|
import { TestHelper } from './test-setup'
|
||||||
|
|
||||||
let testHelper: TestHelper
|
let testHelper: TestHelper
|
||||||
@@ -221,4 +225,32 @@ describe('k8s utils', () => {
|
|||||||
expect(() => containerPorts({ portMappings: ['1/tcp/udp'] })).toThrow()
|
expect(() => containerPorts({ portMappings: ['1/tcp/udp'] })).toThrow()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('generate container name', () => {
|
||||||
|
it('should return the container name from image string', () => {
|
||||||
|
expect(
|
||||||
|
generateContainerName('public.ecr.aws/localstack/localstack')
|
||||||
|
).toEqual('localstack')
|
||||||
|
expect(
|
||||||
|
generateContainerName(
|
||||||
|
'public.ecr.aws/url/with/multiple/slashes/postgres:latest'
|
||||||
|
)
|
||||||
|
).toEqual('postgres')
|
||||||
|
expect(generateContainerName('postgres')).toEqual('postgres')
|
||||||
|
expect(generateContainerName('postgres:latest')).toEqual('postgres')
|
||||||
|
expect(generateContainerName('localstack/localstack')).toEqual(
|
||||||
|
'localstack'
|
||||||
|
)
|
||||||
|
expect(generateContainerName('localstack/localstack:latest')).toEqual(
|
||||||
|
'localstack'
|
||||||
|
)
|
||||||
|
})
|
||||||
|
|
||||||
|
it('should throw on invalid image string', () => {
|
||||||
|
expect(() =>
|
||||||
|
generateContainerName('localstack/localstack/:latest')
|
||||||
|
).toThrow()
|
||||||
|
expect(() => generateContainerName(':latest')).toThrow()
|
||||||
|
})
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import * as fs from 'fs'
|
import * as fs from 'fs'
|
||||||
import * as path from 'path'
|
import * as path from 'path'
|
||||||
import { cleanupJob } from '../src/hooks'
|
import { cleanupJob } from '../src/hooks'
|
||||||
import { prepareJob } from '../src/hooks/prepare-job'
|
import { createContainerSpec, prepareJob } from '../src/hooks/prepare-job'
|
||||||
import { TestHelper } from './test-setup'
|
import { TestHelper } from './test-setup'
|
||||||
|
import { generateContainerName } from '../src/k8s/utils'
|
||||||
|
import { V1Container } from '@kubernetes/client-node'
|
||||||
|
|
||||||
jest.useRealTimers()
|
jest.useRealTimers()
|
||||||
|
|
||||||
@@ -71,4 +73,13 @@ describe('Prepare job', () => {
|
|||||||
prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
||||||
).rejects.toThrow()
|
).rejects.toThrow()
|
||||||
})
|
})
|
||||||
|
|
||||||
|
it('should not set command + args for service container if not passed in args', async () => {
|
||||||
|
const services = prepareJobData.args.services.map(service => {
|
||||||
|
return createContainerSpec(service, generateContainerName(service.image))
|
||||||
|
}) as [V1Container]
|
||||||
|
|
||||||
|
expect(services[0].command).toBe(undefined)
|
||||||
|
expect(services[0].args).toBe(undefined)
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
Reference in New Issue
Block a user