Implement yaml extensions overwriting the default pod/container spec (#75)

* Implement yaml extensions overwriting the default pod/container spec

* format files

* Extend specs for container job and include docker and k8s tests in k8s

* Create table tests for docker tests

* included warnings and extracted append logic as generic

* updated merge to allow for file read

* reverted back examples and k8s/tests

* reverted back docker tests

* Tests for extension prepare-job

* Fix lint and format and merge error

* Added basic test for container step

* revert hooklib since new definition for container options is received from a file

* revert docker options since create options are a string

* Fix revert

* Update package locks and deps

* included example of extension.yaml. Added side-car container that was missing

* Ignore spec modification for the service containers, change selector to

* fix lint error

* Add missing image override

* Add comment explaining merge object meta with job and pod

* fix test
This commit is contained in:
Nikola Jokic
2023-09-25 11:49:03 +02:00
committed by GitHub
parent 5107bb1d41
commit 4cdcf09c43
13 changed files with 672 additions and 102 deletions

View File

@@ -1,7 +1,12 @@
import * as core from '@actions/core'
import * as io from '@actions/io'
import * as k8s from '@kubernetes/client-node'
import { ContextPorts, prepareJobArgs, writeToResponseFile } from 'hooklib'
import {
JobContainerInfo,
ContextPorts,
PrepareJobArgs,
writeToResponseFile
} from 'hooklib'
import path from 'path'
import {
containerPorts,
@@ -15,12 +20,14 @@ import {
DEFAULT_CONTAINER_ENTRY_POINT,
DEFAULT_CONTAINER_ENTRY_POINT_ARGS,
generateContainerName,
mergeContainerWithOptions,
readExtensionFromFile,
PodPhase
} from '../k8s/utils'
import { JOB_CONTAINER_NAME } from './constants'
import { JOB_CONTAINER_EXTENSION_NAME, JOB_CONTAINER_NAME } from './constants'
export async function prepareJob(
args: prepareJobArgs,
args: PrepareJobArgs,
responseFile
): Promise<void> {
if (!args.container) {
@@ -28,26 +35,46 @@ export async function prepareJob(
}
await prunePods()
const extension = readExtensionFromFile()
await copyExternalsToRoot()
let container: k8s.V1Container | undefined = undefined
if (args.container?.image) {
core.debug(`Using image '${args.container.image}' for job image`)
container = createContainerSpec(args.container, JOB_CONTAINER_NAME, true)
container = createContainerSpec(
args.container,
JOB_CONTAINER_NAME,
true,
extension
)
}
let services: k8s.V1Container[] = []
if (args.services?.length) {
services = args.services.map(service => {
core.debug(`Adding service '${service.image}' to pod definition`)
return createContainerSpec(service, generateContainerName(service.image))
return createContainerSpec(
service,
generateContainerName(service.image),
false,
undefined
)
})
}
if (!container && !services?.length) {
throw new Error('No containers exist, skipping hook invocation')
}
let createdPod: k8s.V1Pod | undefined = undefined
try {
createdPod = await createPod(container, services, args.container.registry)
createdPod = await createPod(
container,
services,
args.container.registry,
extension
)
} catch (err) {
await prunePods()
throw new Error(`failed to create job pod: ${err}`)
@@ -153,9 +180,10 @@ async function copyExternalsToRoot(): Promise<void> {
}
export function createContainerSpec(
container,
container: JobContainerInfo,
name: string,
jobContainer = false
jobContainer = false,
extension?: k8s.V1PodTemplateSpec
): k8s.V1Container {
if (!container.entryPoint && jobContainer) {
container.entryPoint = DEFAULT_CONTAINER_ENTRY_POINT
@@ -193,5 +221,17 @@ export function createContainerSpec(
jobContainer
)
if (!extension) {
return podContainer
}
const from = extension.spec?.containers?.find(
c => c.name === JOB_CONTAINER_EXTENSION_NAME
)
if (from) {
mergeContainerWithOptions(podContainer, from)
}
return podContainer
}