Skip to content
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
115 changes: 61 additions & 54 deletions frontend/src/old-pages/Configure/Cluster.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ import {
CheckboxProps,
Container,
FormField,
Header,
Select,
SpaceBetween,
} from '@cloudscape-design/components'
Expand All @@ -38,7 +37,10 @@ import {useFeatureFlag} from '../../feature-flags/useFeatureFlag'
import {createComputeResource as singleCreate} from './Queues/SingleInstanceComputeResource'
import {createComputeResource as multiCreate} from './Queues/MultiInstanceComputeResource'
import {MultiUser, multiUserValidate} from './MultiUser'
import {NonCancelableEventHandler} from '@cloudscape-design/components/internal/events'
import {
NonCancelableCustomEvent,
NonCancelableEventHandler,
} from '@cloudscape-design/components/internal/events'
import TitleDescriptionHelpPanel from '../../components/help-panel/TitleDescriptionHelpPanel'
import {useHelpPanel} from '../../components/help-panel/HelpPanel'
import {useCallback, useMemo} from 'react'
Expand All @@ -47,6 +49,7 @@ import {SelectProps} from '@cloudscape-design/components/select/interfaces'

// Constants
const errorsPath = ['app', 'wizard', 'errors', 'cluster']
const configPath = ['app', 'wizard', 'config']

const selectQueues = (state: any) =>
getState(state, ['app', 'wizard', 'config', 'Scheduling', 'SlurmQueues'])
Expand Down Expand Up @@ -112,23 +115,34 @@ function RegionSelect() {
const {t} = useTranslation()
const region =
useState(['app', 'wizard', 'config', 'Region']) || 'Please select a region.'
const queues = useSelector(selectQueues)
const editing = useState(['app', 'wizard', 'editing'])
const config = useState(configPath)
const isMultipleInstanceTypesActive = useFeatureFlag(
'queues_multiple_instance_types',
)

const handleChange = ({detail}: any) => {
const chosenRegion =
detail.selectedOption.value === 'Default'
? null
: detail.selectedOption.value
LoadAwsConfig(chosenRegion)
setState(['app', 'wizard', 'vpc'], null)
setState(['app', 'wizard', 'headNode', 'subnet'], null)
if (queues)
queues.forEach((_queue: any, i: any) => {
clearState(['app', 'wizard', 'queues', i, 'subnet'])
})
setState(['app', 'wizard', 'config', 'Region'], chosenRegion)
}
const handleChange = useCallback(
({detail}: NonCancelableCustomEvent<SelectProps.ChangeDetail>) => {
const chosenRegion = detail.selectedOption.value

if (!chosenRegion) return

/**
* Clear wizard state
*
* We keep the part of the state that is necessary
* to continue with the experience
*/
const {page, source, clusterName, errors} =
getState(['app', 'wizard']) || {}
setState(['app', 'wizard'], {page, source, clusterName, errors})

initWizardState(config, chosenRegion, isMultipleInstanceTypesActive)

LoadAwsConfig(chosenRegion)
},
[config, isMultipleInstanceTypesActive],
)

const supportedRegions = [
'af-south-1',
Expand Down Expand Up @@ -181,6 +195,35 @@ function RegionSelect() {
)
}

function initWizardState(
config: Record<string, unknown>,
region: string,
isMultipleInstanceTypesActive: boolean,
) {
const customAMIEnabled = getIn(config, ['Image', 'CustomAmi']) ? true : false
setState(['app', 'wizard', 'customAMI', 'enabled'], customAMIEnabled)
setState([...configPath, 'HeadNode', 'InstanceType'], 't2.micro')
setState([...configPath, 'Scheduling', 'Scheduler'], 'slurm')
setState([...configPath, 'Region'], region)
setState([...configPath, 'Image', 'Os'], 'alinux2')
setState(
[...configPath, 'Scheduling', 'SlurmQueues'],
[
{
Name: 'queue0',
AllocationStrategy: isMultipleInstanceTypesActive
? 'lowest-price'
: undefined,
ComputeResources: [
isMultipleInstanceTypesActive
? multiCreate(0, 0)
: singleCreate(0, 0),
],
},
],
)
}

function OsSelect() {
const {t} = useTranslation()
const oses: [string, string][] = [
Expand Down Expand Up @@ -341,7 +384,6 @@ function VpcSelect() {
function Cluster() {
const {t} = useTranslation()
const editing = useState(['app', 'wizard', 'editing'])
const configPath = ['app', 'wizard', 'config']
let config = useState(configPath)
let clusterConfig = useState(['app', 'wizard', 'clusterConfigYaml']) || ''
let wizardLoaded = useState(['app', 'wizard', 'loaded'])
Expand All @@ -357,7 +399,6 @@ function Cluster() {
useHelpPanel(<ClusterPropertiesHelpPanel />)

React.useEffect(() => {
const configPath = ['app', 'wizard', 'config']
// Don't overwrite the config if we go back, still gets overwritten
// after going forward so need to consider better way of handling this
if (clusterConfig) return
Expand All @@ -366,46 +407,12 @@ function Cluster() {
if (!wizardLoaded) {
setState(['app', 'wizard', 'loaded'], true)
if (!config) {
const customAMIEnabled = getIn(config, ['Image', 'CustomAmi'])
? true
: false
setState(['app', 'wizard', 'customAMI', 'enabled'], customAMIEnabled)
setState([...configPath, 'HeadNode', 'InstanceType'], 't2.micro')
setState([...configPath, 'Scheduling', 'Scheduler'], 'slurm')
setState([...configPath, 'Region'], region)
setState([...configPath, 'Image', 'Os'], 'alinux2')
setState(
[...configPath, 'Scheduling', 'SlurmQueues'],
[
{
Name: 'queue0',
AllocationStrategy: isMultipleInstanceTypesActive
? 'lowest-price'
: undefined,
ComputeResources: [
isMultipleInstanceTypesActive
? multiCreate(0, 0)
: singleCreate(0, 0),
],
},
],
)
}
}

// Load these values when we get a new config as well (e.g. changing region)
if (awsConfig && awsConfig.keypairs && awsConfig.keypairs.length > 0) {
const keypairs = getState(['aws', 'keypairs']) || []
const keypairNames = new Set(keypairs.map((kp: any) => kp.KeyName))
const headNodeKPPath = [...configPath, 'HeadNode', 'Ssh', 'KeyName']
if (keypairs.length > 0 && !keypairNames.has(getState(headNodeKPPath))) {
setState(headNodeKPPath, awsConfig.keypairs[0].KeyName)
initWizardState(config, region, isMultipleInstanceTypesActive)
}
}
}, [
region,
config,
awsConfig,
clusterConfig,
wizardLoaded,
isMultipleInstanceTypesActive,
Expand Down
32 changes: 20 additions & 12 deletions frontend/src/old-pages/Configure/HeadNode.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import i18next from 'i18next'
import {Trans, useTranslation} from 'react-i18next'
import {useSelector} from 'react-redux'
import {findFirst, getIn} from '../../util'
import safeGet from 'lodash/get'

// UI Elements
import {
Expand Down Expand Up @@ -61,6 +62,7 @@ import {useHelpPanel} from '../../components/help-panel/HelpPanel'
// Constants
const headNodePath = ['app', 'wizard', 'config', 'HeadNode']
const errorsPath = ['app', 'wizard', 'errors', 'headNode']
const keypairPath = [...headNodePath, 'Ssh', 'KeyName']

function headNodeValidate() {
const subnetPath = [...headNodePath, 'Networking', 'SubnetId']
Expand Down Expand Up @@ -210,28 +212,34 @@ function enableSsm(enable: any) {
}
}
}
const setKeyPair = (kpValue?: string) => {
if (kpValue) setState(keypairPath, kpValue)
else {
clearState([...headNodePath, 'Ssh'])
enableSsm(true)
}
}

function KeypairSelect() {
const {t} = useTranslation()
const keypairs = useState(['aws', 'keypairs']) || []
const keypairPath = [...headNodePath, 'Ssh', 'KeyName']
const keypair = useState(keypairPath) || ''
const keypairsInAWSConfig = useState(['aws', 'keypairs'])
const selectedKeypairName = useState(keypairPath)
const editing = useState(['app', 'wizard', 'editing'])
const keypairToOption = (kp: any) => {
if (kp === 'None' || kp === null || kp === undefined)
return {label: 'None', value: null}
else return {label: kp.KeyName, value: kp.KeyName}
}

const keypairsWithNone = ['None', ...keypairs]
const keypairsWithNone = ['None', ...keypairsInAWSConfig]

const setKeyPair = (kpValue: any) => {
if (kpValue) setState(keypairPath, kpValue)
else {
clearState([...headNodePath, 'Ssh'])
enableSsm(true)
React.useEffect(() => {
const firstAvailableKeypair = safeGet(keypairsInAWSConfig, ['0', 'KeyName'])
if (!selectedKeypairName && firstAvailableKeypair) {
setKeyPair(firstAvailableKeypair)
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [keypairsInAWSConfig])

return (
<FormField
Expand All @@ -241,8 +249,8 @@ function KeypairSelect() {
<Select
disabled={editing}
selectedOption={keypairToOption(
findFirst(keypairs, (x: any) => {
return x.KeyName === keypair
findFirst(keypairsInAWSConfig, (x: any) => {
return x.KeyName === selectedKeypairName
}),
)}
onChange={({detail}) => {
Expand Down