diff --git a/packages/api-v4/src/cloudpulse/types.ts b/packages/api-v4/src/cloudpulse/types.ts index 4b64bf16c30..765a1d71ba1 100644 --- a/packages/api-v4/src/cloudpulse/types.ts +++ b/packages/api-v4/src/cloudpulse/types.ts @@ -148,14 +148,13 @@ export interface CreateAlertDefinitionPayload { rule_criteria: { rules: MetricCriteria[]; }; - triggerCondition: TriggerCondition; + trigger_condition: TriggerCondition; channel_ids: number[]; } export interface MetricCriteria { metric: string; aggregation_type: MetricAggregationType; operator: MetricOperatorType; - value: number; dimension_filters: DimensionFilter[]; } diff --git a/packages/manager/package.json b/packages/manager/package.json index 85c4c8ef960..e7db26ddf7f 100644 --- a/packages/manager/package.json +++ b/packages/manager/package.json @@ -19,7 +19,7 @@ "@dnd-kit/utilities": "^3.2.2", "@emotion/react": "^11.11.1", "@emotion/styled": "^11.11.0", - "@hookform/resolvers": "2.9.11", + "@hookform/resolvers": "3.9.1", "@linode/api-v4": "*", "@linode/design-language-system": "^2.6.1", "@linode/search": "*", diff --git a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/CreateAlertDefinition.tsx b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/CreateAlertDefinition.tsx index 61a6822075e..7132fae1455 100644 --- a/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/CreateAlertDefinition.tsx +++ b/packages/manager/src/features/CloudPulse/Alerts/CreateAlert/CreateAlertDefinition.tsx @@ -19,6 +19,7 @@ import { filterFormValues, filterMetricCriteriaFormValues } from './utilities'; import type { CreateAlertDefinitionForm, MetricCriteriaForm } from './types'; import type { TriggerCondition } from '@linode/api-v4/lib/cloudpulse/types'; +import type { ObjectSchema } from 'yup'; const triggerConditionInitialValues: TriggerCondition = { evaluation_period_seconds: 0, @@ -30,7 +31,6 @@ const criteriaInitialValues: MetricCriteriaForm = { dimension_filters: [], metric: '', operator: null, - value: 0, }; const initialValues: CreateAlertDefinitionForm = { channel_ids: [], @@ -43,7 +43,7 @@ const initialValues: CreateAlertDefinitionForm = { }, serviceType: null, severity: null, - triggerCondition: triggerConditionInitialValues, + trigger_condition: triggerConditionInitialValues, }; const overrides = [ @@ -65,7 +65,9 @@ export const CreateAlertDefinition = () => { const formMethods = useForm({ defaultValues: initialValues, mode: 'onBlur', - resolver: yupResolver(CreateAlertDefinitionFormSchema), + resolver: yupResolver( + CreateAlertDefinitionFormSchema as ObjectSchema + ), }); const { diff --git a/packages/manager/src/features/Images/ImagesCreate/ImageUpload.utils.ts b/packages/manager/src/features/Images/ImagesCreate/ImageUpload.utils.ts index 8e890f341f7..c326350ea26 100644 --- a/packages/manager/src/features/Images/ImagesCreate/ImageUpload.utils.ts +++ b/packages/manager/src/features/Images/ImagesCreate/ImageUpload.utils.ts @@ -28,7 +28,9 @@ export interface ImageUploadFormData extends ImageUploadPayload { * form state at once. */ export const ImageUploadSchema = uploadImageSchema.shape({ - file: mixed().required('Image is required.'), + file: mixed((input): input is File => input instanceof File).required( + 'Image is required.' + ), }); /** diff --git a/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts b/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts index c782b611884..fb31fae09cf 100644 --- a/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts +++ b/packages/manager/src/features/Linodes/LinodeCreate/resolvers.ts @@ -18,8 +18,10 @@ import type { LinodeCreateFormContext, LinodeCreateFormValues, } from './utilities'; +import type { CreateLinodeRequest } from '@linode/api-v4'; import type { QueryClient } from '@tanstack/react-query'; import type { FieldErrors, Resolver } from 'react-hook-form'; +import type { ObjectSchema } from 'yup'; export const getLinodeCreateResolver = ( tab: LinodeCreateType | undefined, @@ -30,9 +32,9 @@ export const getLinodeCreateResolver = ( const transformedValues = getLinodeCreatePayload(structuredClone(values)); const { errors } = await yupResolver( - schema, + schema as ObjectSchema, {}, - { mode: 'async', rawValues: true } + { mode: 'async', raw: true } )(transformedValues, context, options); if (tab === 'Clone Linode' && !values.linode) { diff --git a/packages/validation/src/buckets.schema.ts b/packages/validation/src/buckets.schema.ts index bb14be983a4..0f5c6a02668 100644 --- a/packages/validation/src/buckets.schema.ts +++ b/packages/validation/src/buckets.schema.ts @@ -47,8 +47,17 @@ export const CreateBucketSchema = object() }), endpoint_type: string() .oneOf([...ENDPOINT_TYPES]) - .notRequired(), - cors_enabled: boolean().notRequired(), + .optional(), + cors_enabled: boolean().optional(), + acl: string() + .oneOf([ + 'private', + 'public-read', + 'authenticated-read', + 'public-read-write', + ]) + .optional(), + s3_endpoint: string().optional(), }, [['cluster', 'region']] ) diff --git a/packages/validation/src/cloudpulse.schema.ts b/packages/validation/src/cloudpulse.schema.ts index c639deb9d7d..c7a0317e268 100644 --- a/packages/validation/src/cloudpulse.schema.ts +++ b/packages/validation/src/cloudpulse.schema.ts @@ -16,10 +16,9 @@ const metricCriteria = object({ dimension_filters: array().of(dimensionFilters).notRequired(), }); -const triggerCondition = object({ - criteria_condition: string().required('Criteria condition is required.'), - polling_interval_seconds: string().required('Polling Interval is required.'), - evaluation_period_seconds: string().required( +const trigger_condition = object({ + polling_interval_seconds: number().required('Polling Interval is required.'), + evaluation_period_seconds: number().required( 'Evaluation Period is required.' ), trigger_occurrences: number() @@ -30,10 +29,15 @@ const triggerCondition = object({ export const createAlertDefinitionSchema = object({ label: string().required('Name is required.'), description: string().optional(), - severity: string().required('Severity is required.'), - entity_ids: array().of(string()).min(1, 'At least one resource is needed.'), - criteria: array() - .of(metricCriteria) - .min(1, 'At least one metric criteria is needed.'), - triggerCondition, + severity: number().oneOf([0, 1, 2, 3]).required('Severity is required.'), + entity_ids: array() + .of(string().required()) + .min(1, 'At least one resource is needed.'), + rule_criteria: object({ + rules: array() + .of(metricCriteria) + .min(1, 'At least one metric criteria is needed.'), + }), + trigger_condition, + channel_ids: array(number()), }); diff --git a/packages/validation/src/images.schema.ts b/packages/validation/src/images.schema.ts index c8b3b6f9a45..de9470a17eb 100644 --- a/packages/validation/src/images.schema.ts +++ b/packages/validation/src/images.schema.ts @@ -9,10 +9,10 @@ const labelSchema = string() ); export const baseImageSchema = object({ - label: labelSchema.notRequired(), - description: string().notRequired().min(1).max(65000), - cloud_init: boolean().notRequired(), - tags: array(string().min(3).max(50)).max(500).notRequired(), + label: labelSchema.optional(), + description: string().optional().min(1).max(65000), + cloud_init: boolean().optional(), + tags: array(string().min(3).max(50).required()).max(500).optional(), }); export const createImageSchema = baseImageSchema.shape({ @@ -27,11 +27,11 @@ export const uploadImageSchema = baseImageSchema.shape({ }); export const updateImageSchema = object({ - label: labelSchema.notRequired(), + label: labelSchema.optional(), description: string() - .notRequired() + .optional() .max(65000, 'Length must be 65000 characters or less.'), - tags: array(string()).notRequired(), + tags: array(string().required()).optional(), }); export const updateImageRegionsSchema = object({ diff --git a/packages/validation/src/kubernetes.schema.ts b/packages/validation/src/kubernetes.schema.ts index b16ecd24493..8789aaa34ae 100644 --- a/packages/validation/src/kubernetes.schema.ts +++ b/packages/validation/src/kubernetes.schema.ts @@ -62,13 +62,13 @@ export const createKubeClusterSchema = object().shape({ .min(1, 'Please add at least one node pool.'), }); -export const ipv4Address = string().test({ +export const ipv4Address = string().defined().test({ name: 'validateIP', message: 'Must be a valid IPv4 address.', test: validateIP, }); -export const ipv6Address = string().test({ +export const ipv6Address = string().defined().test({ name: 'validateIP', message: 'Must be a valid IPv6 address.', test: validateIP, @@ -77,10 +77,12 @@ export const ipv6Address = string().test({ const controlPlaneACLOptionsSchema = object().shape({ enabled: boolean(), 'revision-id': string(), - addresses: object().shape({ - ipv4: array().of(ipv4Address).nullable(), - ipv6: array().of(ipv6Address).nullable(), - }), + addresses: object() + .shape({ + ipv4: array().of(ipv4Address).nullable(), + ipv6: array().of(ipv6Address).nullable(), + }) + .notRequired(), }); export const kubernetesControlPlaneACLPayloadSchema = object().shape({ diff --git a/yarn.lock b/yarn.lock index 6ac23dd6a46..70c5aef2080 100644 --- a/yarn.lock +++ b/yarn.lock @@ -949,10 +949,10 @@ dependencies: levn "^0.4.1" -"@hookform/resolvers@2.9.11": - version "2.9.11" - resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-2.9.11.tgz#9ce96e7746625a89239f68ca57c4f654264c17ef" - integrity sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ== +"@hookform/resolvers@3.9.1": + version "3.9.1" + resolved "https://registry.yarnpkg.com/@hookform/resolvers/-/resolvers-3.9.1.tgz#a23883c40bfd449cb6c6ab5a0fa0729184c950ff" + integrity sha512-ud2HqmGBM0P0IABqoskKWI6PEf6ZDDBZkFqe2Vnl+mTHCEHzr3ISjjZyCwTjC/qpL25JC9aIDkloQejvMeq0ug== "@humanwhocodes/config-array@^0.5.0": version "0.5.0"