Skip to content

Commit

Permalink
Fix [Batch Run] Does not adjust based on function version (#2110)
Browse files Browse the repository at this point in the history
  • Loading branch information
mavdryk authored Dec 7, 2023
1 parent 347f952 commit 58b4c83
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 162 deletions.
5 changes: 4 additions & 1 deletion src/components/JobWizard/JobWizard.js
Original file line number Diff line number Diff line change
Expand Up @@ -411,7 +411,7 @@ const JobWizard = ({
ref: scheduleButtonRef
},
{
id:'run-btn',
id: 'run-btn',
label:
mode === PANEL_EDIT_MODE
? 'Save'
Expand Down Expand Up @@ -483,11 +483,14 @@ const JobWizard = ({
/>
<JobWizardRunDetails
formState={formState}
frontendSpec={frontendSpec}
isBatchInference={isBatchInference}
isEditMode={isEditMode}
jobAdditionalData={jobAdditionalData}
params={params}
prePopulatedData={prePopulatedData}
selectedFunctionData={selectedFunctionData}
setJobData={setJobData}
/>
<JobWizardDataInputs formState={formState} />
<JobWizardParameters formState={formState} />
Expand Down
211 changes: 72 additions & 139 deletions src/components/JobWizard/JobWizard.util.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ import {
merge,
omit,
set,
unionBy
some
} from 'lodash'
import {
ADVANCED_STEP,
Expand Down Expand Up @@ -83,7 +83,6 @@ import { generateObjectFromKeyValue, parseObjectToKeyValue } from 'igz-controls/
import { getDefaultSchedule, scheduleDataInitialState } from '../SheduleWizard/scheduleWizard.util'
import { getErrorDetail } from 'igz-controls/utils/common.util'
import { getPreemptionMode } from '../../utils/getPreemptionMode'
import { isEveryObjectValueEmpty } from '../../utils/isEveryObjectValueEmpty'
import { trimSplit } from '../../utils'

const volumeTypesMap = {
Expand All @@ -105,21 +104,21 @@ export const generateJobWizardData = (
defaultData,
currentProjectName,
isEditMode,
prePopulatedData
prePopulatedData,
selectedVersion
) => {
const functions = selectedFunctionData.functions
const functionInfo = getFunctionInfo(selectedFunctionData)
const functionInfo = getFunctionInfo(selectedFunctionData, selectedVersion)
const defaultResources = frontendSpec?.default_function_pod_resources ?? {}
const functionParameters = getFunctionParameters(functions, functionInfo.handler)
const [functionPriorityClassName] = getFunctionPriorityClass(functions)
const [limits] = getLimits(functions)
const [requests] = getRequests(functions)
const environmentVariables = getEnvironmentVariables(functions)
const [preemptionMode] = getFunctionPreemptionMode(functions)
const functionParameters = getFunctionParameters(functionInfo.function, functionInfo.handler)
const functionPriorityClassName = getFunctionPriorityClass(functionInfo.function)
const limits = getLimits(functionInfo.function)
const requests = getRequests(functionInfo.function)
const environmentVariables = getEnvironmentVariables(functionInfo.function)
const preemptionMode = getFunctionPreemptionMode(functionInfo.function)
const jobPriorityClassName =
functionPriorityClassName || frontendSpec.default_function_priority_class_name || ''
const nodeSelectorTable = getNodeSelectors(functions)
const volumesTable = getVolumesData(functions)
const nodeSelectorTable = getNodeSelectors(functionInfo.function)
const volumesTable = getVolumes(functionInfo.function)
const gpuType = getLimitsGpuType(limits)
const scheduleData = defaultData?.schedule
? getDefaultSchedule(defaultData.schedule)
Expand Down Expand Up @@ -203,15 +202,15 @@ export const generateJobWizardData = (

export const generateJobWizardDefaultData = (
frontendSpec,
selectedFunctionData,
selectedFunction,
defaultData,
currentProjectName,
isEditMode
) => {
if (isEmpty(defaultData)) return [{}, {}]

const runInfo = getRunDefaultInfo(defaultData, selectedFunctionData)
const functionParameters = getFunctionDefaultParameters(selectedFunctionData, runInfo.handler)
const runInfo = getRunDefaultInfo(defaultData, selectedFunction)
const functionParameters = getFunctionDefaultParameters(selectedFunction, runInfo.handler)
const [predefinedParameters, customParameters] = parseDefaultParameters(
functionParameters,
defaultData.task.spec.parameters,
Expand Down Expand Up @@ -241,7 +240,7 @@ export const generateJobWizardDefaultData = (
handler: runInfo.handler,
handlerData: runInfo.handlerData,
labels: runInfo.labels,
image: parseImageData(selectedFunctionData, frontendSpec, currentProjectName)
image: parseImageData(selectedFunction, frontendSpec, currentProjectName)
},
[DATA_INPUTS_STEP]: {
dataInputsTable: parseDefaultDataInputs(functionParameters, defaultData.task.spec.inputs)
Expand Down Expand Up @@ -299,12 +298,9 @@ export const generateJobWizardDefaultData = (
return [jobFormData, jobAdditionalData]
}

export const getHandlerData = (selectedFunctionData, handler) => {
const currentFunction = selectedFunctionData?.functions
? chain(selectedFunctionData.functions).orderBy('metadata.updated', 'desc').get(0).value()
: selectedFunctionData
const handlerData = get(currentFunction, ['spec', 'entry_points', handler], {})
const outputs = (handlerData?.outputs ?? []).filter(output => !isEveryObjectValueEmpty(output))
export const getHandlerData = (selectedFunction, handler) => {
const handlerData = get(selectedFunction, ['spec', 'entry_points', handler], {})
const outputs = (handlerData?.outputs ?? []).filter(output => output.type)

return {
doc: handlerData?.doc,
Expand All @@ -313,109 +309,96 @@ export const getHandlerData = (selectedFunctionData, handler) => {
}
}

const getFunctionInfo = selectedFunctionData => {
const getFunctionInfo = (selectedFunctionData, preSelectedVersion) => {
const functions = selectedFunctionData?.functions

if (!isEmpty(functions)) {
const versionOptions = getVersionOptions(functions)
const handlerOptions = getHandlerOptions(functions)
const { defaultVersion, defaultHandler } = getDefaultHandlerAndVersion(
versionOptions,
handlerOptions,
functions
)
const currentFunctionVersion = selectedFunctionData.tag || defaultVersion
const currentFunction =
functions.find(func => func.metadata.tag === currentFunctionVersion) ?? functions[0]
const selectedVersion = some(versionOptions, { id: preSelectedVersion })
? preSelectedVersion
: getDefaultVersion(versionOptions)
const handlerOptions = getHandlerOptions(functions, selectedVersion)
const defaultHandler = getDefaultHandler(handlerOptions, functions, selectedVersion)
const selectedFunction = getSelectedFunction(functions, selectedVersion)

return {
name: selectedFunctionData.name,
handler: defaultHandler,
version: currentFunctionVersion,
handlerData: getHandlerData(currentFunction, defaultHandler),
version: selectedVersion,
handlerData: getHandlerData(selectedFunction, defaultHandler),
handlerOptions,
versionOptions,
function: currentFunction || {}
function: selectedFunction || {}
}
}
}

const getRunDefaultInfo = (defaultData, selectedFunctionData) => {
const getRunDefaultInfo = (defaultData, selectedFunction) => {
return {
labels: parseChipsData(defaultData.task?.metadata?.labels),
name: defaultData.task?.metadata?.name || '',
handler: defaultData.task?.spec?.handler,
handlerData: getHandlerData(selectedFunctionData, defaultData.task?.spec?.handler),
handlerData: getHandlerData(selectedFunction, defaultData.task?.spec?.handler),
handlerOptions: [],
version: '',
versionOptions: []
}
}

const getHandlerOptions = selectedFunctions => {
const getHandlerOptions = (selectedFunctions, selectedVersion) => {
return chain(selectedFunctions)
.map(func => Object.values(func.spec?.entry_points ?? {}))
.find(func => func.metadata.tag === selectedVersion)
.get('spec.entry_points', {})
.values()
.flatten()
.map(entry_point => ({
label: entry_point.name,
id: entry_point.name,
subLabel: entry_point.doc
}))
.uniqBy('label')
.value()
}

const getVersionOptions = selectedFunctions => {
const versionOptions = unionBy(
selectedFunctions.map(func => {
const versionOptions = chain(selectedFunctions)
.map(func => {
if (!func.metadata.tag) return null

return {
label: func.metadata.tag || 'N/A',
id: func.metadata.tag || TAG_NA
}
}),
'id'
)
})
.compact()
.unionBy('id')
.value()

return versionOptions.length ? versionOptions : [{ label: 'N/A', id: TAG_NA }]
}

const getDefaultHandler = (handlerOptions, selectedFunctions) => {
const getDefaultHandler = (handlerOptions, selectedFunctions, selectedVersion) => {
let handler = ''

const latestFunction = selectedFunctions.find(item => item.metadata.tag === TAG_LATEST)
const selectedFunction = selectedFunctions.find(item => item.metadata.tag === selectedVersion)

if (handlerOptions.length) {
handler = handlerOptions[0]?.id
} else if (latestFunction) {
handler = latestFunction.spec.default_handler || FUNCTION_DEFAULT_HANDLER
} else {
handler = selectedFunctions[0]?.spec.default_handler || FUNCTION_DEFAULT_HANDLER
handler = selectedFunction?.spec?.default_handler || FUNCTION_DEFAULT_HANDLER
}

return handler
}

const getDefaultHandlerAndVersion = (versionOptions, handlerOptions, selectedFunctions) => {
const defaultVersion =
versionOptions.find(version => version.id === TAG_LATEST)?.id || versionOptions[0].id || ''

const defaultHandler = getDefaultHandler(handlerOptions, selectedFunctions)
const getDefaultVersion = versionOptions => {
return versionOptions.find(version => version.id === TAG_LATEST)?.id || versionOptions[0].id || ''
}

return {
defaultVersion,
defaultHandler
}
const getSelectedFunction = (functions, selectedVersion) => {
return functions.find(func => func.metadata.tag === selectedVersion) ?? functions[0]
}

export const getFunctionParameters = (selectedFunction, handler) => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.entry_points ? func.spec.entry_points[handler]?.parameters ?? [] : []
})
.flatten()
.unionBy('name')
.value()
return get(selectedFunction, ['spec', 'entry_points', handler, 'parameters'], [])
}

export const getFunctionDefaultParameters = (selectedFunction, handler) => {
Expand All @@ -425,72 +408,27 @@ export const getFunctionDefaultParameters = (selectedFunction, handler) => {
}

const getFunctionPriorityClass = selectedFunction => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.priority_class_name
})
.flatten()
.unionBy('name')
.value()
return get(selectedFunction, 'spec.priority_class_name', '')
}

const getLimits = selectedFunction => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.resources?.limits ? func.spec.resources?.limits : {}
})
.filter(limits => !isEveryObjectValueEmpty(limits))
.flatten()
.unionBy('name')
.value()
return get(selectedFunction, 'spec.resources.limits', {})
}

const getRequests = selectedFunction => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.resources?.requests ? func.spec.resources.requests : {}
})
.filter(request => !isEveryObjectValueEmpty(request))
.flatten()
.unionBy('name')
.value()
return get(selectedFunction, 'spec.resources.requests', {})
}

const getEnvironmentVariables = selectedFunction => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.env ?? []
})
.flatten()
.unionBy('name')
.value()
return get(selectedFunction, 'spec.env', [])
}

const getFunctionPreemptionMode = selectedFunction => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.preemption_mode ?? ''
})
.flatten()
.unionBy('key')
.value()
return get(selectedFunction, 'spec.preemption_mode', '')
}

const getNodeSelectors = selectedFunction => {
return chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => {
return func.spec.node_selector ?? {}
})
.map(parseObjectToKeyValue)
.flatten()
.unionBy('data.key')
.value()
return parseObjectToKeyValue(get(selectedFunction, 'spec.node_selector', {}))
}

const getVolumeType = volume => {
Expand All @@ -505,20 +443,9 @@ const getVolumeType = volume => {
}
}

const getVolumesData = selectedFunction => {
const volumes = chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => func.spec.volumes ?? [])
.flatten()
.unionBy('name')
.value()

const volumeMounts = chain(selectedFunction)
.orderBy('metadata.updated', 'desc')
.map(func => func.spec.volume_mounts ?? [])
.flatten()
.unionBy('name')
.value()
const getVolumes = selectedFunction => {
const volumes = get(selectedFunction, 'spec.volumes', [])
const volumeMounts = get(selectedFunction, 'spec.volume_mounts', [])

return parseVolumes(volumes, volumeMounts)
}
Expand Down Expand Up @@ -922,13 +849,19 @@ const generateParameters = parametersTableData => {
parametersTableData?.predefined
?.filter(parameter => !parameter.data.isHyper && parameter.data.isChecked)
.forEach(parameter => {
parameters[parameter.data.name] = convertParameterValue(parameter.data.value, parameter.data.type)
parameters[parameter.data.name] = convertParameterValue(
parameter.data.value,
parameter.data.type
)
})

parametersTableData?.custom
?.filter(parameter => !parameter.data.isHyper && parameter.data.isChecked)
.forEach(parameter => {
parameters[parameter.data.name] = convertParameterValue(parameter.data.value, parameter.data.type)
parameters[parameter.data.name] = convertParameterValue(
parameter.data.value,
parameter.data.type
)
})

return parameters
Expand Down Expand Up @@ -1061,10 +994,10 @@ export const generateJobRequestData = (
mode,
isSchedule
) => {
let selectedFunction = selectedFunctionData?.functions?.find(
func => func.metadata.tag === formData[RUN_DETAILS_STEP].version
const selectedFunction = getSelectedFunction(
selectedFunctionData?.functions,
formData[RUN_DETAILS_STEP].version
)
selectedFunction ??= selectedFunctionData?.functions?.[0]
const [volume_mounts, volumes] = generateVolumes(formData[RESOURCES_STEP].volumesTable)

const postData = {
Expand Down
Loading

0 comments on commit 58b4c83

Please sign in to comment.