144 lines
4.5 KiB
TypeScript
144 lines
4.5 KiB
TypeScript
import * as fs from 'fs'
|
|
import { cleanupJob } from '../src/hooks'
|
|
import { prepareJob } from '../src/hooks/prepare-job'
|
|
import { TestHelper } from './test-setup'
|
|
import { getPodByName } from '../src/k8s'
|
|
import { ENV_USE_KUBE_SCHEDULER } from '../src/k8s/utils'
|
|
|
|
jest.useRealTimers()
|
|
|
|
let testHelper: TestHelper
|
|
let prepareJobData: any
|
|
let prepareJobOutputFilePath: string
|
|
|
|
describe('RWO Affinity Behavior (Scheduler Mode)', () => {
|
|
beforeEach(async () => {
|
|
testHelper = new TestHelper()
|
|
await testHelper.initialize()
|
|
prepareJobData = testHelper.getPrepareJobDefinition()
|
|
prepareJobOutputFilePath = testHelper.createFile('prepare-job-output.json')
|
|
})
|
|
|
|
afterEach(async () => {
|
|
await cleanupJob()
|
|
await testHelper.cleanup()
|
|
delete process.env[ENV_USE_KUBE_SCHEDULER]
|
|
})
|
|
|
|
it('should add nodeAffinity with hostname selector when scheduler mode is enabled', async () => {
|
|
process.env[ENV_USE_KUBE_SCHEDULER] = 'true'
|
|
|
|
await prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
|
|
|
const content = JSON.parse(
|
|
fs.readFileSync(prepareJobOutputFilePath).toString()
|
|
)
|
|
|
|
const pod = await getPodByName(content.state.jobPod)
|
|
|
|
expect(pod.spec?.affinity).toBeDefined()
|
|
expect(pod.spec?.affinity?.nodeAffinity).toBeDefined()
|
|
|
|
const nodeAffinity = pod.spec?.affinity?.nodeAffinity
|
|
expect(
|
|
nodeAffinity?.requiredDuringSchedulingIgnoredDuringExecution
|
|
).toBeDefined()
|
|
|
|
const nodeSelectorTerms =
|
|
nodeAffinity?.requiredDuringSchedulingIgnoredDuringExecution
|
|
?.nodeSelectorTerms
|
|
|
|
expect(nodeSelectorTerms).toBeDefined()
|
|
expect(nodeSelectorTerms?.length).toBeGreaterThan(0)
|
|
|
|
const matchExpressions = nodeSelectorTerms?.[0].matchExpressions
|
|
expect(matchExpressions).toBeDefined()
|
|
expect(matchExpressions?.length).toBeGreaterThan(0)
|
|
|
|
const hostnameExpression = matchExpressions?.[0]
|
|
expect(hostnameExpression?.key).toBe('kubernetes.io/hostname')
|
|
expect(hostnameExpression?.operator).toBe('In')
|
|
|
|
expect(hostnameExpression?.values).toBeDefined()
|
|
expect(hostnameExpression?.values?.length).toBeGreaterThan(0)
|
|
expect(hostnameExpression?.values?.[0]).toBeTruthy()
|
|
})
|
|
|
|
it('should NOT add nodeAffinity when scheduler mode is disabled', async () => {
|
|
process.env[ENV_USE_KUBE_SCHEDULER] = 'false'
|
|
|
|
await prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
|
|
|
const content = JSON.parse(
|
|
fs.readFileSync(prepareJobOutputFilePath).toString()
|
|
)
|
|
|
|
const pod = await getPodByName(content.state.jobPod)
|
|
|
|
if (pod.spec?.affinity) {
|
|
expect(pod.spec.affinity.nodeAffinity).toBeUndefined()
|
|
}
|
|
|
|
expect(pod.spec?.nodeName).toBeDefined()
|
|
})
|
|
|
|
it('should fail assertion if affinity block is missing when scheduler mode is enabled', async () => {
|
|
process.env[ENV_USE_KUBE_SCHEDULER] = 'true'
|
|
|
|
await prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
|
|
|
const content = JSON.parse(
|
|
fs.readFileSync(prepareJobOutputFilePath).toString()
|
|
)
|
|
|
|
const pod = await getPodByName(content.state.jobPod)
|
|
|
|
expect(pod.spec?.affinity).toBeDefined()
|
|
expect(pod.spec?.affinity?.nodeAffinity).toBeDefined()
|
|
expect(
|
|
pod.spec?.affinity?.nodeAffinity
|
|
?.requiredDuringSchedulingIgnoredDuringExecution
|
|
).toBeDefined()
|
|
|
|
const nodeSelectorTerms =
|
|
pod.spec?.affinity?.nodeAffinity
|
|
?.requiredDuringSchedulingIgnoredDuringExecution?.nodeSelectorTerms
|
|
|
|
expect(nodeSelectorTerms?.[0]?.matchExpressions?.[0]?.key).toBe(
|
|
'kubernetes.io/hostname'
|
|
)
|
|
expect(nodeSelectorTerms?.[0]?.matchExpressions?.[0]?.operator).toBe('In')
|
|
expect(
|
|
nodeSelectorTerms?.[0]?.matchExpressions?.[0]?.values?.length
|
|
).toBeGreaterThan(0)
|
|
})
|
|
|
|
it('should use correct node name from runner pod in affinity values', async () => {
|
|
process.env[ENV_USE_KUBE_SCHEDULER] = 'true'
|
|
|
|
const runnerPodName = process.env.ACTIONS_RUNNER_POD_NAME
|
|
|
|
await prepareJob(prepareJobData.args, prepareJobOutputFilePath)
|
|
|
|
const content = JSON.parse(
|
|
fs.readFileSync(prepareJobOutputFilePath).toString()
|
|
)
|
|
|
|
const jobPod = await getPodByName(content.state.jobPod)
|
|
|
|
const runnerPod = await getPodByName(runnerPodName!)
|
|
|
|
const affinityValues =
|
|
jobPod.spec?.affinity?.nodeAffinity
|
|
?.requiredDuringSchedulingIgnoredDuringExecution?.nodeSelectorTerms?.[0]
|
|
?.matchExpressions?.[0]?.values
|
|
|
|
expect(affinityValues).toBeDefined()
|
|
expect(affinityValues?.length).toBeGreaterThan(0)
|
|
|
|
if (runnerPod.spec?.nodeName) {
|
|
expect(affinityValues).toContain(runnerPod.spec.nodeName)
|
|
}
|
|
})
|
|
})
|