diff --git a/app/react/portainer/settings/SettingsView/AutoHealPanel/validation.ts b/app/react/portainer/settings/SettingsView/AutoHealPanel/validation.ts index c0059ae10..0e79a38ba 100644 --- a/app/react/portainer/settings/SettingsView/AutoHealPanel/validation.ts +++ b/app/react/portainer/settings/SettingsView/AutoHealPanel/validation.ts @@ -1,48 +1,16 @@ import { SchemaOf, boolean, mixed, object, string } from 'yup'; import { AutoHealScope } from '../../types'; +import { durationPattern, parseGoDurationSeconds } from '../parseGoDuration'; import { Values } from './types'; -// Matches Go's time.ParseDuration units (e.g. "30s", "1m30s", "2h"). -const durationPattern = /^(\d+(\.\d+)?(ns|us|µs|ms|s|m|h))+$/; - // Lower bound for the check interval, kept in sync with the backend // (minAutoHealCheckInterval). A near-zero interval would hammer Docker with // list/inspect calls for no benefit, and the backend rejects it (400), so the // front-end must reject it too rather than letting a sub-second value through. const minCheckIntervalSeconds = 1; -// Seconds per Go duration unit, used to evaluate the configured interval against -// the floor. Mirrors the units accepted by durationPattern. -const unitSeconds: Record = { - ns: 1e-9, - us: 1e-6, - µs: 1e-6, - ms: 1e-3, - s: 1, - m: 60, - h: 3600, -}; - -// parseGoDurationSeconds converts a Go-style duration (e.g. "1h30m") to seconds, -// or returns null when the string is not a well-formed duration. -function parseGoDurationSeconds(value: string): number | null { - if (!durationPattern.test(value)) { - return null; - } - - let total = 0; - const componentPattern = /(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)/g; - let match = componentPattern.exec(value); - while (match !== null) { - total += parseFloat(match[1]) * unitSeconds[match[2]]; - match = componentPattern.exec(value); - } - - return total; -} - export function validation(): SchemaOf { return object({ enabled: boolean().default(false), diff --git a/app/react/portainer/settings/SettingsView/AutoUpdatePanel/validation.ts b/app/react/portainer/settings/SettingsView/AutoUpdatePanel/validation.ts index 5870b7f9c..214221026 100644 --- a/app/react/portainer/settings/SettingsView/AutoUpdatePanel/validation.ts +++ b/app/react/portainer/settings/SettingsView/AutoUpdatePanel/validation.ts @@ -1,12 +1,10 @@ import { SchemaOf, boolean, mixed, object, string } from 'yup'; import { AutoUpdateScope } from '../../types'; +import { durationPattern, parseGoDurationSeconds } from '../parseGoDuration'; import { Values } from './types'; -// Matches Go's time.ParseDuration units (e.g. "6h", "30m", "1h30m"). -const durationPattern = /^(\d+(\.\d+)?(ns|us|µs|ms|s|m|h))+$/; - // Lower bound for the poll interval, kept in sync with the backend // (minAutoUpdatePollInterval). Polling more often than this only adds registry // load: the image-status cache (~5m) bounds detection latency, so a sub-minute @@ -18,36 +16,6 @@ const minPollIntervalSeconds = 60; // container can pass its healthcheck, defeating the gate. const minRollbackTimeoutSeconds = 10; -// Seconds per Go duration unit, used to evaluate the configured interval against -// the floor. Mirrors the units accepted by durationPattern. -const unitSeconds: Record = { - ns: 1e-9, - us: 1e-6, - µs: 1e-6, - ms: 1e-3, - s: 1, - m: 60, - h: 3600, -}; - -// parseGoDurationSeconds converts a Go-style duration (e.g. "1h30m") to seconds, -// or returns null when the string is not a well-formed duration. -function parseGoDurationSeconds(value: string): number | null { - if (!durationPattern.test(value)) { - return null; - } - - let total = 0; - const componentPattern = /(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)/g; - let match = componentPattern.exec(value); - while (match !== null) { - total += parseFloat(match[1]) * unitSeconds[match[2]]; - match = componentPattern.exec(value); - } - - return total; -} - export function validation(): SchemaOf { return object({ enabled: boolean().default(false), diff --git a/app/react/portainer/settings/SettingsView/parseGoDuration.ts b/app/react/portainer/settings/SettingsView/parseGoDuration.ts new file mode 100644 index 000000000..c2cd02c25 --- /dev/null +++ b/app/react/portainer/settings/SettingsView/parseGoDuration.ts @@ -0,0 +1,32 @@ +// Matches Go's time.ParseDuration units (e.g. "6h", "30m", "1h30m"). +export const durationPattern = /^(\d+(\.\d+)?(ns|us|µs|ms|s|m|h))+$/; + +// Seconds per Go duration unit, used to evaluate a configured interval against a +// floor. Mirrors the units accepted by durationPattern. +const unitSeconds: Record = { + ns: 1e-9, + us: 1e-6, + µs: 1e-6, + ms: 1e-3, + s: 1, + m: 60, + h: 3600, +}; + +// parseGoDurationSeconds converts a Go-style duration (e.g. "1h30m") to seconds, +// or returns null when the string is not a well-formed duration. +export function parseGoDurationSeconds(value: string): number | null { + if (!durationPattern.test(value)) { + return null; + } + + let total = 0; + const componentPattern = /(\d+(?:\.\d+)?)(ns|us|µs|ms|s|m|h)/g; + let match = componentPattern.exec(value); + while (match !== null) { + total += parseFloat(match[1]) * unitSeconds[match[2]]; + match = componentPattern.exec(value); + } + + return total; +}