slight refactor, bring pod phase to k8s lib, better types

This commit is contained in:
Thomas Boop
2022-06-06 22:39:28 -04:00
parent 1bfc52f466
commit cd310988c9
6 changed files with 49 additions and 37 deletions

View File

@@ -74,14 +74,6 @@ export enum Protocol {
UDP = 'udp'
}
export enum PodPhase {
PENDING = 'Pending',
RUNNING = 'Running',
SUCCEEDED = 'Succeeded',
FAILED = 'Failed',
UNKNOWN = 'Unknown'
}
export interface PrepareJobResponse {
state?: object
context?: ContainerContext

View File

@@ -2,11 +2,12 @@ import * as core from '@actions/core'
import * as io from '@actions/io'
import * as k8s from '@kubernetes/client-node'
import {
ContextPorts,
PodPhase,
prepareJobArgs,
writeToResponseFile
} from 'hooklib'
containerVolumes,
DEFAULT_CONTAINER_ENTRY_POINT,
DEFAULT_CONTAINER_ENTRY_POINT_ARGS
} from '../k8s/utils'
import { ContextPorts, prepareJobArgs, writeToResponseFile } from 'hooklib'
import path from 'path'
import {
containerPorts,
@@ -18,11 +19,6 @@ import {
requiredPermissions,
waitForPodPhases
} from '../k8s'
import {
containerVolumes,
DEFAULT_CONTAINER_ENTRY_POINT,
DEFAULT_CONTAINER_ENTRY_POINT_ARGS
} from '../k8s/utils'
import { JOB_CONTAINER_NAME } from './constants'
export async function prepareJob(
@@ -40,14 +36,14 @@ export async function prepareJob(
await copyExternalsToRoot()
let container: k8s.V1Container | undefined = undefined
if (args.container?.image) {
core.info(`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)
}
let services: k8s.V1Container[] = []
if (args.services?.length) {
services = args.services.map(service => {
core.info(`Adding service '${service.image}' to pod definition`)
core.debug(`Adding service '${service.image}' to pod definition`)
return createPodSpec(service, service.image.split(':')[0])
})
}
@@ -65,6 +61,9 @@ export async function prepareJob(
if (!createdPod?.metadata?.name) {
throw new Error('created pod should have metadata.name')
}
core.debug(
`Job pod created, waiting for it to come online ${createdPod?.metadata?.name}`
)
try {
await waitForPodPhases(
@@ -77,7 +76,7 @@ export async function prepareJob(
throw new Error(`Pod failed to come online with error: ${err}`)
}
core.info('Pod is ready for traffic')
core.debug('Job pod is ready for traffic')
let isAlpine = false
try {
@@ -88,7 +87,7 @@ export async function prepareJob(
} catch (err) {
throw new Error(`Failed to determine if the pod is alpine: ${err}`)
}
core.debug(`Setting isAlpine to ${isAlpine}`)
generateResponseFile(responseFile, createdPod, isAlpine)
}
@@ -160,7 +159,6 @@ function createPodSpec(
name: string,
jobContainer = false
): k8s.V1Container {
core.info(JSON.stringify(container))
if (!container.entryPointArgs) {
container.entryPointArgs = DEFAULT_CONTAINER_ENTRY_POINT_ARGS
}

View File

@@ -1,6 +1,6 @@
import * as k8s from '@kubernetes/client-node'
import * as core from '@actions/core'
import { PodPhase } from 'hooklib'
import { RunContainerStepArgs } from 'hooklib'
import {
createJob,
createSecretForEnvs,
@@ -11,18 +11,20 @@ import {
waitForPodPhases
} from '../k8s'
import { JOB_CONTAINER_NAME } from './constants'
import { containerVolumes } from '../k8s/utils'
import { containerVolumes, PodPhase } from '../k8s/utils'
export async function runContainerStep(stepContainer): Promise<number> {
export async function runContainerStep(
stepContainer: RunContainerStepArgs
): Promise<number> {
if (stepContainer.dockerfile) {
throw new Error('Building container actions is not currently supported')
}
let secretName: string | undefined = undefined
if (stepContainer['environmentVariables']) {
secretName = await createSecretForEnvs(
stepContainer['environmentVariables']
)
core.debug('')
if (stepContainer.environmentVariables) {
secretName = await createSecretForEnvs(stepContainer.environmentVariables)
}
core.debug(`Created secret ${secretName} for container job envs`)
const container = createPodSpec(stepContainer, secretName)
const job = await createJob(container)
if (!job.metadata?.name) {
@@ -32,27 +34,37 @@ export async function runContainerStep(stepContainer): Promise<number> {
)} to have correctly set the metadata.name`
)
}
core.debug(`Job created, waiting for pod to start: ${job.metadata?.name}`)
const podName = await getContainerJobPodName(job.metadata.name)
await waitForPodPhases(
podName,
new Set([PodPhase.COMPLETED, PodPhase.RUNNING, PodPhase.SUCCEEDED]),
new Set([PodPhase.PENDING, PodPhase.UNKNOWN])
)
core.debug('Container step is running or complete, pulling logs')
await getPodLogs(podName, JOB_CONTAINER_NAME)
core.debug('Waiting for container job to complete')
await waitForJobToComplete(job.metadata.name)
// pod has failed so pull the status code from the container
const status = await getPodStatus(podName)
if (!status?.containerStatuses?.length) {
core.warning(`Can't determine container status`)
return 0
core.error(
`Can't determine container status from response: ${JSON.stringify(
status
)}`
)
return 1
}
const exitCode =
status.containerStatuses[status.containerStatuses.length - 1].state
?.terminated?.exitCode
return Number(exitCode) || 0
return Number(exitCode) || 1
}
function createPodSpec(container, secretName?: string): k8s.V1Container {
function createPodSpec(
container: RunContainerStepArgs,
secretName?: string
): k8s.V1Container {
const podContainer = new k8s.V1Container()
podContainer.name = JOB_CONTAINER_NAME
podContainer.image = container.image

View File

@@ -1,4 +1,5 @@
import { Command, getInputFromStdin, prepareJobArgs } from 'hooklib'
import * as core from '@actions/core'
import {
cleanupJob,
prepareJob,
@@ -34,8 +35,7 @@ async function run(): Promise<void> {
throw new Error(`Command not recognized: ${command}`)
}
} catch (error) {
// eslint-disable-next-line no-console
console.log(error)
core.error(JSON.stringify(error))
exitCode = 1
}
process.exitCode = exitCode

View File

@@ -1,5 +1,5 @@
import * as k8s from '@kubernetes/client-node'
import { ContainerInfo, PodPhase, Registry } from 'hooklib'
import { ContainerInfo, Registry } from 'hooklib'
import * as stream from 'stream'
import {
getJobPodName,
@@ -9,6 +9,7 @@ import {
getVolumeClaimName,
RunnerInstanceLabel
} from '../hooks/constants'
import { PodPhase } from './utils'
const kc = new k8s.KubeConfig()
@@ -355,7 +356,7 @@ async function getPodPhase(podName: string): Promise<PodPhase> {
if (!pod.status?.phase || !podPhaseLookup.has(pod.status.phase)) {
return PodPhase.UNKNOWN
}
return pod.status?.phase
return pod.status?.phase as PodPhase
}
async function isJobSucceeded(jobName: string): Promise<boolean> {

View File

@@ -70,3 +70,12 @@ export function containerVolumes(
return mounts
}
export enum PodPhase {
PENDING = 'Pending',
RUNNING = 'Running',
SUCCEEDED = 'Succeeded',
FAILED = 'Failed',
UNKNOWN = 'Unknown',
COMPLETED = 'Completed'
}