// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may not use this file except in compliance // with the License. A copy of the License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "LICENSE.txt" file accompanying this file. This file is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES // OR CONDITIONS OF ANY KIND, express or implied. See the License for the specific language governing permissions and // limitations under the License. // Fameworks import * as React from 'react' import i18next from 'i18next' import {Trans, useTranslation} from 'react-i18next' import {useSelector} from 'react-redux' import {findFirst, getIn} from '../../util' // UI Elements import { Checkbox, CheckboxProps, Container, FormField, Header, Select, SpaceBetween, } from '@cloudscape-design/components' // State / Model import {getState, setState, useState, clearState} from '../../store' import {LoadAwsConfig} from '../../model' // Components import {CustomAMISettings} from './Components' 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 TitleDescriptionHelpPanel from '../../components/help-panel/TitleDescriptionHelpPanel' import {useHelpPanel} from '../../components/help-panel/HelpPanel' import {useCallback, useMemo} from 'react' import {OptionDefinition} from '@cloudscape-design/components/internal/components/option/interfaces' import {SelectProps} from '@cloudscape-design/components/select/interfaces' // Constants const errorsPath = ['app', 'wizard', 'errors', 'cluster'] const selectQueues = (state: any) => getState(state, ['app', 'wizard', 'config', 'Scheduling', 'SlurmQueues']) const selectVpc = (state: any) => getState(state, ['app', 'wizard', 'vpc']) const selectAwsSubnets = (state: any) => getState(state, ['aws', 'subnets']) function clusterValidate() { const vpc = getState(['app', 'wizard', 'vpc']) const editing = getState(['app', 'wizard', 'editing']) const customAmiEnabled = getState(['app', 'wizard', 'customAMI', 'enabled']) const customAmi = getState(['app', 'wizard', 'config', 'Image', 'CustomAmi']) const multiUserEnabled = getState(['app', 'wizard', 'multiUser']) || false let valid = true setState([...errorsPath, 'validated'], true) if (!editing && !vpc) { setState( [...errorsPath, 'vpc'], i18next.t('wizard.cluster.validation.VpcSelect'), ) valid = false } else { clearState([...errorsPath, 'vpc']) } if (customAmiEnabled && !customAmi) { setState( [...errorsPath, 'customAmi'], i18next.t('wizard.cluster.validation.customAmiSelect'), ) valid = false } else { clearState([...errorsPath, 'customAmi']) } if (multiUserEnabled && !multiUserValidate()) { valid = false } else { clearState([...errorsPath, 'multiUser']) } return valid } function itemToOption( item: string | [string, string] | null, ): SelectProps.Option | null { if (!item) return null let label, value if (typeof item == 'string') { label = item value = item } else { ;[value, label] = item } return {label, value} } 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 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 supportedRegions = [ 'af-south-1', 'ap-east-1', 'ap-northeast-1', 'ap-northeast-2', 'ap-south-1', 'ap-southeast-1', 'ap-southeast-2', 'ca-central-1', 'cn-north-1', 'cn-northwest-1', 'eu-central-1', 'eu-north-1', 'eu-south-1', 'eu-west-1', 'eu-west-2', 'eu-west-3', 'me-south-1', 'sa-east-1', 'us-east-1', 'us-east-2', 'us-gov-east-1', 'us-gov-west-1', 'us-west-1', 'us-west-2', ] return ( <> ) } function VpcSelect() { const {t} = useTranslation() const vpcs = useState(['aws', 'vpcs']) || [] const vpc = useSelector(selectVpc) || '' const error = useState([...errorsPath, 'vpc']) const subnets = useSelector(selectAwsSubnets) const queues = useSelector(selectQueues) const editing = useState(['app', 'wizard', 'editing']) const VpcName = (vpc: any) => { if (!vpc) return null var tags = vpc.Tags if (!tags) { return null } tags = vpc.Tags.filter((t: any) => { return t.Key === 'Name' }) return tags.length > 0 ? tags[0].Value : null } const vpcToDisplayOption = (vpc: any) => { return vpc ? { label: (
{VpcName(vpc) ? VpcName(vpc) : vpc.VpcId}
), value: vpc.VpcId, } : { label:
Select a VPC
, value: null, } } const vpcToOption = (vpc: any) => { return vpc ? { label: (
{vpc.VpcId} {VpcName(vpc) && `(${VpcName(vpc)})`}
), value: vpc.VpcId, } : { label:
Select a VPC
, value: null, } } const setVpc = (vpcId: any) => { setState(['app', 'wizard', 'vpc'], vpcId) setState([...errorsPath, 'vpc'], null) const headNodeSubnetPath = [ 'app', 'wizard', 'config', 'HeadNode', 'Networking', 'SubnetId', ] const filteredSubnets = subnets && subnets.filter((s: any) => { return s.VpcId === vpcId }) if (filteredSubnets.length > 0) { const subnetSet = new Set(filteredSubnets) var subnet = filteredSubnets[0] if (!subnetSet.has(getState(headNodeSubnetPath))) setState(headNodeSubnetPath, subnet.SubnetId) if (queues) queues.forEach((_queue: any, i: any) => { const queueSubnetPath = [ 'app', 'wizard', 'config', 'Scheduling', 'SlurmQueues', i, 'Networking', 'SubnetIds', ] if (!subnetSet.has(getState(queueSubnetPath))) setState(queueSubnetPath, [subnet.SubnetId]) }) } } return (