Skip to content

Commit c8d6d1c

Browse files
authored
[UI] Add Spot policy configuration option to the fleet wizard (#3519)
* [UI] Add Spot policy configuration option to the fleet wizard #3513
1 parent 9c81898 commit c8d6d1c

File tree

7 files changed

+89
-15
lines changed

7 files changed

+89
-15
lines changed

frontend/src/locale/en.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -625,12 +625,14 @@
625625
"name_placeholder": "Optional",
626626
"name_constraint": "Example: 'my-fleet' or 'default'. If not specified, generated automatically.",
627627
"min_instances": "Min number of instances",
628-
"min_instances_description": "Set it `0` to provision instances only when required",
628+
"min_instances_description": "Set it '0' to provision instances only when required",
629629
"max_instances": "Max number of instances",
630630
"max_instances_description": "Required only if you want to set an upper limit",
631631
"max_instances_placeholder": "Optional",
632632
"idle_duration": "Idle duration",
633-
"idle_duration_description": "Example: '0s', '1m', '1h'"
633+
"idle_duration_description": "Example: '0s', '1m', '1h'",
634+
"spot_policy": "Spot policy",
635+
"spot_policy_description": "Set it to 'auto' to allow the use of both on-demand and spot instances"
634636
}
635637
},
636638
"volume": {

frontend/src/pages/Fleets/Add/FleetFormFields/constants.tsx

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,14 @@ import React from 'react';
22
import { get } from 'lodash';
33
import * as yup from 'yup';
44

5+
import { FleetFormFields } from './type';
6+
7+
export const fleetFormDefaultValues: FleetFormFields = {
8+
min_instances: 0,
9+
idle_duration: '5m',
10+
spot_policy: 'auto',
11+
};
12+
513
export const FLEET_MIN_INSTANCES_INFO = {
614
header: <h2>Min number of instances</h2>,
715
body: (
@@ -78,6 +86,26 @@ export const FLEET_IDLE_DURATION_INFO = {
7886
),
7987
};
8088

89+
export const FLEET_SPOT_POLICY_INFO = {
90+
header: <h2>Spot policy</h2>,
91+
body: (
92+
<>
93+
<p>
94+
Some backends may support spot instances, also known as preemptive instances. Such instances come at a
95+
significantly lower price but can be interrupted by the cloud provider at any time.
96+
</p>
97+
<p>
98+
If you set <code>spot_policy</code> to <code>auto</code>, the fleet will allow the use of both types of
99+
instances: <code>on-demand</code> and <code>spot</code>.
100+
</p>
101+
<p>
102+
Note that run configurations must specify their own <code>spot_policy</code>, which by default is always{' '}
103+
<code>on-demand</code>.
104+
</p>
105+
</>
106+
),
107+
};
108+
81109
const requiredFieldError = 'This is required field';
82110
const numberFieldError = 'This is number field';
83111

frontend/src/pages/Fleets/Add/FleetFormFields/index.tsx

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import React from 'react';
22
import { useTranslation } from 'react-i18next';
33

4-
import { FormInput, InfoLink, SpaceBetween } from 'components';
4+
import { FormInput, FormSelect, InfoLink, SpaceBetween } from 'components';
55

66
import { useHelpPanel } from 'hooks';
77

8-
import { FLEET_IDLE_DURATION_INFO, FLEET_MAX_INSTANCES_INFO, FLEET_MIN_INSTANCES_INFO } from './constants';
8+
import {
9+
FLEET_IDLE_DURATION_INFO,
10+
FLEET_MAX_INSTANCES_INFO,
11+
FLEET_MIN_INSTANCES_INFO,
12+
FLEET_SPOT_POLICY_INFO,
13+
} from './constants';
914
import { FleetFormFieldsProps } from './type';
1015

1116
import type { FieldValues } from 'react-hook-form/dist/types/fields';
@@ -64,6 +69,22 @@ export function FleetFormFields<T extends FieldValues = FieldValues>({
6469
type="number"
6570
/>
6671

72+
<FormSelect
73+
info={<InfoLink onFollow={() => openHelpPanel(FLEET_SPOT_POLICY_INFO)} />}
74+
label={t('fleets.edit.spot_policy')}
75+
constraintText={t('fleets.edit.spot_policy_description')}
76+
control={control}
77+
//eslint-disable-next-line @typescript-eslint/ban-ts-comment
78+
// @ts-expect-error
79+
name={getFieldNameWitPrefix(`spot_policy`)}
80+
disabled={disabledAllFields}
81+
options={[
82+
{ label: 'auto', value: 'auto' },
83+
{ label: 'on-demand', value: 'on-demand' },
84+
{ label: 'spot', value: 'spot' },
85+
]}
86+
/>
87+
6788
<FormInput
6889
info={<InfoLink onFollow={() => openHelpPanel(FLEET_IDLE_DURATION_INFO)} />}
6990
label={t('fleets.edit.idle_duration')}

frontend/src/pages/Fleets/Add/FleetFormFields/type.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,5 @@ export type FleetFormFields = {
1212
min_instances: number;
1313
max_instances?: number;
1414
idle_duration?: string;
15+
spot_policy: TSpotPolicy;
1516
};

frontend/src/pages/Fleets/Add/index.tsx

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ import { useApplyFleetMutation } from 'services/fleet';
1515
import { DEFAULT_FLEET_INFO } from 'pages/Project/constants';
1616
import { useYupValidationResolver } from 'pages/Project/hooks/useYupValidationResolver';
1717

18-
import { getMaxInstancesValidator, getMinInstancesValidator, idleDurationValidator } from './FleetFormFields/constants';
18+
import {
19+
fleetFormDefaultValues,
20+
getMaxInstancesValidator,
21+
getMinInstancesValidator,
22+
idleDurationValidator,
23+
} from './FleetFormFields/constants';
1924
import { FleetFormFields } from './FleetFormFields';
2025

2126
import { IFleetWizardForm } from './types';
@@ -33,6 +38,7 @@ const fleetValidationSchema = yup.object({
3338
min_instances: getMinInstancesValidator('max_instances'),
3439
max_instances: getMaxInstancesValidator('min_instances'),
3540
idle_duration: idleDurationValidator,
41+
spot_policy: yup.string().required(requiredFieldError),
3642
});
3743

3844
export const FleetAdd: React.FC = () => {
@@ -52,17 +58,16 @@ export const FleetAdd: React.FC = () => {
5258
const formMethods = useForm<IFleetWizardForm>({
5359
resolver,
5460
defaultValues: {
61+
...fleetFormDefaultValues,
5562
project_name: paramProjectName,
56-
min_instances: 0,
57-
idle_duration: '5m',
5863
},
5964
});
6065

6166
const { handleSubmit, control, clearErrors, trigger, watch, getValues } = formMethods;
6267
const formValues = watch();
6368

6469
const getFormValuesForFleetApplying = (): IApplyFleetPlanRequestRequest => {
65-
const { min_instances, max_instances, idle_duration, name } = getValues();
70+
const { min_instances, max_instances, idle_duration, name, spot_policy } = getValues();
6671

6772
return {
6873
plan: {
@@ -74,6 +79,7 @@ export const FleetAdd: React.FC = () => {
7479
...(max_instances ? { max: max_instances } : {}),
7580
},
7681
...(idle_duration ? { idle_duration } : {}),
82+
spot_policy,
7783
},
7884
profile: {},
7985
},
@@ -185,7 +191,13 @@ export const FleetAdd: React.FC = () => {
185191
};
186192

187193
const getDefaultFleetSummary = () => {
188-
const summaryFields: Array<keyof IFleetWizardForm> = ['name', 'min_instances', 'max_instances', 'idle_duration'];
194+
const summaryFields: Array<keyof IFleetWizardForm> = [
195+
'name',
196+
'min_instances',
197+
'max_instances',
198+
'idle_duration',
199+
'spot_policy',
200+
];
189201

190202
const result: string[] = [];
191203

frontend/src/pages/Project/Add/index.tsx

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { useCreateProjectMutation } from 'services/project';
1616

1717
import { FleetFormFields } from 'pages/Fleets/Add/FleetFormFields';
1818
import {
19+
fleetFormDefaultValues,
1920
getMaxInstancesValidator,
2021
getMinInstancesValidator,
2122
idleDurationValidator,
@@ -51,6 +52,7 @@ const projectValidationSchema = yup.object({
5152
is: true,
5253
then: idleDurationValidator,
5354
}),
55+
spot_policy: yup.string().required(requiredFieldError),
5456
}),
5557
});
5658

@@ -72,9 +74,8 @@ export const ProjectAdd: React.FC = () => {
7274
defaultValues: {
7375
is_public: false,
7476
fleet: {
77+
...fleetFormDefaultValues,
7578
enable_default: true,
76-
min_instances: 0,
77-
idle_duration: '5m',
7879
},
7980
},
8081
});
@@ -93,7 +94,7 @@ export const ProjectAdd: React.FC = () => {
9394

9495
const getFormValuesForFleetApplying = (): IApplyFleetPlanRequestRequest => {
9596
const {
96-
fleet: { min_instances, max_instances, idle_duration, name },
97+
fleet: { min_instances, max_instances, idle_duration, name, spot_policy },
9798
} = getValues();
9899

99100
return {
@@ -106,6 +107,7 @@ export const ProjectAdd: React.FC = () => {
106107
...(max_instances ? { max: max_instances } : {}),
107108
},
108109
...(idle_duration ? { idle_duration } : {}),
110+
spot_policy,
109111
},
110112
profile: {},
111113
},
@@ -231,7 +233,13 @@ export const ProjectAdd: React.FC = () => {
231233
};
232234

233235
const getDefaultFleetSummary = () => {
234-
const summaryFields: Array<keyof IProjectForm['fleet']> = ['name', 'min_instances', 'max_instances', 'idle_duration'];
236+
const summaryFields: Array<keyof IProjectForm['fleet']> = [
237+
'name',
238+
'min_instances',
239+
'max_instances',
240+
'idle_duration',
241+
'spot_policy',
242+
];
235243

236244
const result: string[] = [];
237245

frontend/src/pages/Project/CreateWizard/index.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import { useCreateWizardProjectMutation } from 'services/project';
3030

3131
import { FleetFormFields } from '../../Fleets/Add/FleetFormFields';
3232
import {
33+
fleetFormDefaultValues,
3334
getMaxInstancesValidator,
3435
getMinInstancesValidator,
3536
idleDurationValidator,
@@ -69,6 +70,7 @@ const projectValidationSchema = yup.object({
6970
is: true,
7071
then: idleDurationValidator,
7172
}),
73+
spot_policy: yup.string().required(requiredFieldError),
7274
}),
7375
});
7476

@@ -127,9 +129,8 @@ export const CreateProjectWizard: React.FC = () => {
127129
defaultValues: {
128130
project_type: 'gpu_marketplace',
129131
fleet: {
132+
...fleetFormDefaultValues,
130133
enable_default: true,
131-
min_instances: 0,
132-
idle_duration: '5m',
133134
},
134135
},
135136
});
@@ -319,6 +320,7 @@ export const CreateProjectWizard: React.FC = () => {
319320
'min_instances',
320321
'max_instances',
321322
'idle_duration',
323+
'spot_policy',
322324
];
323325

324326
const result: string[] = [];

0 commit comments

Comments
 (0)