feat: change template max_ttl to default_ttl (#4843)

This commit is contained in:
Garrett Delfosse
2022-11-09 19:36:25 +00:00
committed by GitHub
parent ffc24dcbe0
commit d277e28427
26 changed files with 317 additions and 517 deletions
+3 -6
View File
@@ -179,8 +179,7 @@ export interface CreateTemplateRequest {
readonly icon?: string
readonly template_version_id: string
readonly parameter_values?: CreateParameterRequest[]
readonly max_ttl_ms?: number
readonly min_autostart_interval_ms?: number
readonly default_ttl_ms?: number
}
// From codersdk/templateversions.go
@@ -620,8 +619,7 @@ export interface Template {
readonly build_time_stats: TemplateBuildTimeStats
readonly description: string
readonly icon: string
readonly max_ttl_ms: number
readonly min_autostart_interval_ms: number
readonly default_ttl_ms: number
readonly created_by_id: string
readonly created_by_name: string
}
@@ -700,8 +698,7 @@ export interface UpdateTemplateMeta {
readonly name?: string
readonly description?: string
readonly icon?: string
readonly max_ttl_ms?: number
readonly min_autostart_interval_ms?: number
readonly default_ttl_ms?: number
}
// From codersdk/users.go
@@ -19,7 +19,7 @@ import * as Yup from "yup"
export const Language = {
nameLabel: "Name",
descriptionLabel: "Description",
maxTtlLabel: "Auto-stop limit",
defaultTtlLabel: "Auto-stop default",
iconLabel: "Icon",
formAriaLabel: "Template settings form",
selectEmoji: "Select emoji",
@@ -28,7 +28,7 @@ export const Language = {
descriptionMaxError:
"Please enter a description that is less than or equal to 128 characters.",
ttlHelperText: (ttl: number): string =>
`Workspaces created from this template may not remain running longer than ${ttl} hours.`,
`Workspaces created from this template will default to stopping after ${ttl} hours.`,
}
const MAX_DESCRIPTION_CHAR_LIMIT = 128
@@ -41,7 +41,7 @@ export const validationSchema = Yup.object({
MAX_DESCRIPTION_CHAR_LIMIT,
Language.descriptionMaxError,
),
max_ttl_ms: Yup.number()
default_ttl_ms: Yup.number()
.integer()
.min(0)
.max(24 * MAX_TTL_DAYS /* 7 days in hours */, Language.ttlMaxError),
@@ -72,7 +72,7 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
name: template.name,
description: template.description,
// on display, convert from ms => hours
max_ttl_ms: template.max_ttl_ms / MS_HOUR_CONVERSION,
default_ttl_ms: template.default_ttl_ms / MS_HOUR_CONVERSION,
icon: template.icon,
},
validationSchema,
@@ -80,8 +80,8 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
// on submit, convert from hours => ms
onSubmit({
...formData,
max_ttl_ms: formData.max_ttl_ms
? formData.max_ttl_ms * MS_HOUR_CONVERSION
default_ttl_ms: formData.default_ttl_ms
? formData.default_ttl_ms * MS_HOUR_CONVERSION
: undefined,
})
},
@@ -176,20 +176,20 @@ export const TemplateSettingsForm: FC<TemplateSettingsForm> = ({
</div>
<TextField
{...getFieldHelpers("max_ttl_ms")}
{...getFieldHelpers("default_ttl_ms")}
disabled={isSubmitting}
fullWidth
inputProps={{ min: 0, step: 1 }}
label={Language.maxTtlLabel}
label={Language.defaultTtlLabel}
variant="outlined"
type="number"
/>
{/* If a value for max_ttl_ms has been entered and
{/* If a value for default_ttl_ms has been entered and
there are no validation errors for that field, display helper text.
We do not use the MUI helper-text prop because it overrides the validation error */}
{form.values.max_ttl_ms && !form.errors.max_ttl_ms && (
{form.values.default_ttl_ms && !form.errors.default_ttl_ms && (
<Typography variant="subtitle2">
{Language.ttlHelperText(form.values.max_ttl_ms)}
{Language.ttlHelperText(form.values.default_ttl_ms)}
</Typography>
)}
</Stack>
@@ -26,15 +26,15 @@ const validFormValues = {
name: "Name",
description: "A description",
icon: "A string",
max_ttl_ms: 1,
default_ttl_ms: 1,
}
const fillAndSubmitForm = async ({
name,
description,
max_ttl_ms,
default_ttl_ms,
icon,
}: Omit<Required<UpdateTemplateMeta>, "min_autostart_interval_ms">) => {
}: Required<UpdateTemplateMeta>) => {
const nameField = await screen.findByLabelText(FormLanguage.nameLabel)
await userEvent.clear(nameField)
await userEvent.type(nameField, name)
@@ -49,9 +49,9 @@ const fillAndSubmitForm = async ({
await userEvent.clear(iconField)
await userEvent.type(iconField, icon)
const maxTtlField = await screen.findByLabelText(FormLanguage.maxTtlLabel)
const maxTtlField = await screen.findByLabelText(FormLanguage.defaultTtlLabel)
await userEvent.clear(maxTtlField)
await userEvent.type(maxTtlField, max_ttl_ms.toString())
await userEvent.type(maxTtlField, default_ttl_ms.toString())
const submitButton = await screen.findByText(
FooterFormLanguage.defaultSubmitLabel,
@@ -87,7 +87,7 @@ describe("TemplateSettingsPage", () => {
})
await fillAndSubmitForm(validFormValues)
expect(screen.getByDisplayValue(1)).toBeInTheDocument() // the max_ttl_ms
expect(screen.getByDisplayValue(1)).toBeInTheDocument() // the default_ttl_ms
await waitFor(() => expect(API.updateTemplateMeta).toBeCalledTimes(1))
await waitFor(() =>
@@ -95,7 +95,7 @@ describe("TemplateSettingsPage", () => {
"test-template",
expect.objectContaining({
...validFormValues,
max_ttl_ms: 3600000, // the max_ttl_ms to ms
default_ttl_ms: 3600000, // the default_ttl_ms to ms
}),
),
)
@@ -104,7 +104,7 @@ describe("TemplateSettingsPage", () => {
it("allows a ttl of 7 days", () => {
const values: UpdateTemplateMeta = {
...validFormValues,
max_ttl_ms: 24 * 7,
default_ttl_ms: 24 * 7,
}
const validate = () => validationSchema.validateSync(values)
expect(validate).not.toThrowError()
@@ -113,7 +113,7 @@ describe("TemplateSettingsPage", () => {
it("allows ttl of 0", () => {
const values: UpdateTemplateMeta = {
...validFormValues,
max_ttl_ms: 0,
default_ttl_ms: 0,
}
const validate = () => validationSchema.validateSync(values)
expect(validate).not.toThrowError()
@@ -122,7 +122,7 @@ describe("TemplateSettingsPage", () => {
it("disallows a ttl of 7 days + 1 hour", () => {
const values: UpdateTemplateMeta = {
...validFormValues,
max_ttl_ms: 24 * 7 + 1,
default_ttl_ms: 24 * 7 + 1,
}
const validate = () => validationSchema.validateSync(values)
expect(validate).toThrowError(FormLanguage.ttlMaxError)
+1 -2
View File
@@ -198,8 +198,7 @@ export const MockTemplate: TypesGen.Template = {
delete_ms: 3000,
},
description: "This is a test description.",
max_ttl_ms: 24 * 60 * 60 * 1000,
min_autostart_interval_ms: 60 * 60 * 1000,
default_ttl_ms: 24 * 60 * 60 * 1000,
created_by_id: "test-creator-id",
created_by_name: "test_creator",
icon: "/icon/code.svg",
+4 -4
View File
@@ -52,7 +52,7 @@ describe("maxDeadline", () => {
it("should be never be greater than global max deadline", () => {
const template: Template = {
...Mocks.MockTemplate,
max_ttl_ms: 25 * 60 * 60 * 1000,
default_ttl_ms: 25 * 60 * 60 * 1000,
}
// Then: deadlineMinusDisabled should be falsy
@@ -65,7 +65,7 @@ describe("maxDeadline", () => {
it("should be never be greater than global max deadline", () => {
const template: Template = {
...Mocks.MockTemplate,
max_ttl_ms: 4 * 60 * 60 * 1000,
default_ttl_ms: 4 * 60 * 60 * 1000,
}
// Then: deadlineMinusDisabled should be falsy
@@ -95,7 +95,7 @@ describe("canExtendDeadline", () => {
it("should be falsy if the deadline is more than the template max_ttl", () => {
const tooFarAhead = dayjs().add(
dayjs.duration(Mocks.MockTemplate.max_ttl_ms, "milliseconds"),
dayjs.duration(Mocks.MockTemplate.default_ttl_ms, "milliseconds"),
)
expect(
canExtendDeadline(tooFarAhead, Mocks.MockWorkspace, Mocks.MockTemplate),
@@ -104,7 +104,7 @@ describe("canExtendDeadline", () => {
it("should be truth if the deadline is within the template max_ttl", () => {
const okDeadline = dayjs().add(
dayjs.duration(Mocks.MockTemplate.max_ttl_ms / 2, "milliseconds"),
dayjs.duration(Mocks.MockTemplate.default_ttl_ms / 2, "milliseconds"),
)
expect(
canExtendDeadline(okDeadline, Mocks.MockWorkspace, Mocks.MockTemplate),
+1 -1
View File
@@ -139,7 +139,7 @@ export function getMaxDeadline(
}
const startedAt = dayjs(ws.latest_build.updated_at)
const maxTemplateDeadline = startedAt.add(
dayjs.duration(tpl.max_ttl_ms, "milliseconds"),
dayjs.duration(tpl.default_ttl_ms, "milliseconds"),
)
const maxGlobalDeadline = startedAt.add(deadlineExtensionMax)
return dayjs.min(maxTemplateDeadline, maxGlobalDeadline)