Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix [Batch Run] Does not adjust based on function version #2110

Merged
merged 1 commit into from
Dec 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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