From c0d50b1d50a1f083105afd877a2c370dfcb34dd8 Mon Sep 17 00:00:00 2001 From: Maxime Beauchamp <15185355+baktun14@users.noreply.github.com> Date: Sun, 13 Oct 2024 23:04:05 -0400 Subject: [PATCH] fix(deployment): templates new deploy (#403) --- .../deployments/DeploymentListRow.tsx | 4 +-- .../new-deployment/NewDeploymentContainer.tsx | 13 +++++---- .../src/components/sdl/MemoryFormControl.tsx | 8 +++--- .../src/components/sdl/PersistentStorage.tsx | 6 ++--- .../src/components/sdl/SSHKeyFromControl.tsx | 14 +++++----- .../src/components/sdl/StorageFormControl.tsx | 6 ++--- apps/deploy-web/src/types/sdlBuilder.ts | 21 ++++++++++----- apps/deploy-web/src/utils/akash/units.ts | 27 +++++++++++++------ apps/deploy-web/src/utils/sdl/data.ts | 1 + .../tests/deploy-hello-world.spec.ts | 1 + 10 files changed, 61 insertions(+), 40 deletions(-) diff --git a/apps/deploy-web/src/components/deployments/DeploymentListRow.tsx b/apps/deploy-web/src/components/deployments/DeploymentListRow.tsx index 3f95c7a24..4ce7e4c07 100644 --- a/apps/deploy-web/src/components/deployments/DeploymentListRow.tsx +++ b/apps/deploy-web/src/components/deployments/DeploymentListRow.tsx @@ -239,7 +239,7 @@ export const DeploymentListRow: React.FunctionComponent = ({ deployment, {isManagedWallet ? ( ) : ( - `${escrowBalanceInDenom} {denomData?.label}` + `${escrowBalanceInDenom} ${denomData?.label}` )} @@ -249,7 +249,7 @@ export const DeploymentListRow: React.FunctionComponent = ({ deployment, {isManagedWallet ? ( ) : ( - `${udenomToDenom(amountSpent || 0, 2)} ${denomData?.label}` + `${udenomToDenom(amountSpent || 0, 2)} ${denomData?.label}` )} diff --git a/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx b/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx index 5103f688d..72ce0719a 100644 --- a/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx +++ b/apps/deploy-web/src/components/new-deployment/NewDeploymentContainer.tsx @@ -22,7 +22,6 @@ export const NewDeploymentContainer: FC = () => { const [activeStep, setActiveStep] = useState(null); const [selectedTemplate, setSelectedTemplate] = useState(null); const [editedManifest, setEditedManifest] = useState(null); - const [isInit, setIsInit] = useState(false); const deploySdl = useAtomValue(sdlStore.deploySdl); const { getDeploymentData } = useLocalNotes(); const { getTemplateById } = useTemplates(); @@ -33,12 +32,14 @@ export const NewDeploymentContainer: FC = () => { useEffect(() => { const queryStep = searchParams?.get("step"); - const _activeStep = getStepIndexByParam(queryStep); + const _activeStep = getStepIndexByParam(queryStep as RouteStep); setActiveStep(_activeStep); }, [searchParams]); useEffect(() => { - if (!templates || editedManifest || isInit) return; + const templateId = searchParams?.get("templateId"); + const isCreating = !!activeStep && activeStep > getStepIndexByParam(RouteStep.chooseTemplate); + if (!templates || (isCreating && !!editedManifest && !!templateId)) return; const template = getRedeployTemplate() || getGalleryTemplate(); @@ -54,11 +55,9 @@ export const NewDeploymentContainer: FC = () => { if (queryStep !== RouteStep.editDeployment) { router.replace(UrlService.newDeployment({ ...searchParams, step: RouteStep.editDeployment })); } - - setIsInit(true); } // eslint-disable-next-line react-hooks/exhaustive-deps - }, [templates, editedManifest, searchParams, router, toggleCmp, hasComponent, isInit]); + }, [templates, editedManifest, searchParams, router, toggleCmp, hasComponent, activeStep]); const getRedeployTemplate = () => { let template: Partial | null = null; @@ -112,7 +111,7 @@ export const NewDeploymentContainer: FC = () => { return null; }; - function getStepIndexByParam(step) { + function getStepIndexByParam(step: (typeof RouteStep)[keyof typeof RouteStep] | null) { switch (step) { case RouteStep.editDeployment: return 1; diff --git a/apps/deploy-web/src/components/sdl/MemoryFormControl.tsx b/apps/deploy-web/src/components/sdl/MemoryFormControl.tsx index 53a31a12a..887109168 100644 --- a/apps/deploy-web/src/components/sdl/MemoryFormControl.tsx +++ b/apps/deploy-web/src/components/sdl/MemoryFormControl.tsx @@ -75,7 +75,7 @@ export const MemoryFormControl: React.FunctionComponent = ({ control, ser name={`services.${serviceIndex}.profile.ramUnit`} defaultValue="" render={({ field }) => ( - @@ -83,7 +83,7 @@ export const MemoryFormControl: React.FunctionComponent = ({ control, ser {memoryUnits.map(t => { return ( - + {t.suffix} ); @@ -99,11 +99,11 @@ export const MemoryFormControl: React.FunctionComponent = ({ control, ser field.onChange(newValue)} + onValueChange={newValue => field.onChange(newValue[0])} className="pt-2" /> diff --git a/apps/deploy-web/src/components/sdl/PersistentStorage.tsx b/apps/deploy-web/src/components/sdl/PersistentStorage.tsx index 9b497206c..f84ba6339 100644 --- a/apps/deploy-web/src/components/sdl/PersistentStorage.tsx +++ b/apps/deploy-web/src/components/sdl/PersistentStorage.tsx @@ -92,7 +92,7 @@ export const PersistentStorage: React.FunctionComponent = ({ currentServi name={`services.${serviceIndex}.profile.persistentStorageUnit`} defaultValue="" render={({ field }) => ( - @@ -100,7 +100,7 @@ export const PersistentStorage: React.FunctionComponent = ({ currentServi {storageUnits.map(t => { return ( - + {t.suffix} ); @@ -115,7 +115,7 @@ export const PersistentStorage: React.FunctionComponent = ({ currentServi {currentService.profile.hasPersistentStorage && ( - field.onChange(newValue)} className="pt-2" /> + field.onChange(newValue)} className="pt-2" /> )} diff --git a/apps/deploy-web/src/components/sdl/SSHKeyFromControl.tsx b/apps/deploy-web/src/components/sdl/SSHKeyFromControl.tsx index 9345eb882..28c74fcd7 100644 --- a/apps/deploy-web/src/components/sdl/SSHKeyFromControl.tsx +++ b/apps/deploy-web/src/components/sdl/SSHKeyFromControl.tsx @@ -61,22 +61,24 @@ export const SSHKeyFormControl: FC = ({ control, serviceIndex, } - placeholder="ssh-..." + placeholder="Enter your own pub key: ssh-.." className="flex-grow" inputClassName="pr-[100px]" value={field.value} onChange={event => field.onChange(event.target.value || "")} startIcon={} - endIcon={ - - } data-testid="ssh-public-key-input" /> )} /> +
+ Or + +
+ {hasGenerated && (

How to use

diff --git a/apps/deploy-web/src/components/sdl/StorageFormControl.tsx b/apps/deploy-web/src/components/sdl/StorageFormControl.tsx index 756386ba0..c2b3cb6ff 100644 --- a/apps/deploy-web/src/components/sdl/StorageFormControl.tsx +++ b/apps/deploy-web/src/components/sdl/StorageFormControl.tsx @@ -78,7 +78,7 @@ export const StorageFormControl: React.FunctionComponent = ({ control, se name={`services.${serviceIndex}.profile.storageUnit`} defaultValue="" render={({ field }) => ( - @@ -86,7 +86,7 @@ export const StorageFormControl: React.FunctionComponent = ({ control, se {storageUnits.map(t => { return ( - + {t.suffix} ); @@ -102,7 +102,7 @@ export const StorageFormControl: React.FunctionComponent = ({ control, se { - const currentUnit = memoryUnits.find(u => ramUnit === u.suffix); + const currentUnit = memoryUnits.find(u => ramUnit.toLowerCase() === u.suffix.toLowerCase()); const _value = (value || 0) * (currentUnit?.value || 0); + const maxValue = bytesToShrink(validationConfig.maxMemory); + const maxGroupValue = bytesToShrink(validationConfig.maxGroupMemory); + if (serviceCount === 1 && _value < validationConfig.minMemory) { context.addIssue({ code: z.ZodIssueCode.custom, @@ -239,7 +245,7 @@ const validateMemoryAmount = (value: number, ramUnit: string, serviceCount: numb } else if (serviceCount === 1 && _value > validationConfig.maxMemory) { context.addIssue({ code: z.ZodIssueCode.custom, - message: `Maximum amount of memory for a single service instance is 512 Gi.`, + message: `Maximum amount of memory for a single service instance is ${roundDecimal(maxValue.value, 2)} ${maxValue.unit}.`, path: ["profile", "ram"], fatal: true }); @@ -247,7 +253,7 @@ const validateMemoryAmount = (value: number, ramUnit: string, serviceCount: numb } else if (serviceCount > 1 && serviceCount * _value > validationConfig.maxGroupMemory) { context.addIssue({ code: z.ZodIssueCode.custom, - message: `Maximum total amount of memory for a single service instance group is 1024 Gi.`, + message: `Maximum total amount of memory for a single service instance group is ${roundDecimal(maxGroupValue.value, 2)} ${maxGroupValue.unit}.`, path: ["profile", "ram"], fatal: true }); @@ -256,8 +262,9 @@ const validateMemoryAmount = (value: number, ramUnit: string, serviceCount: numb }; const validateStorageAmount = (value: number, storageUnit: string, serviceCount: number, context: z.RefinementCtx) => { - const currentUnit = memoryUnits.find(u => storageUnit === u.suffix); + const currentUnit = storageUnits.find(u => storageUnit.toLowerCase() === u.suffix.toLowerCase()); const _value = (value || 0) * (currentUnit?.value || 0); + const maxValue = bytesToShrink(validationConfig.maxStorage); if (serviceCount === 1 && _value < validationConfig.minStorage) { context.addIssue({ @@ -270,7 +277,7 @@ const validateStorageAmount = (value: number, storageUnit: string, serviceCount: } else if (serviceCount === 1 && _value > validationConfig.maxStorage) { context.addIssue({ code: z.ZodIssueCode.custom, - message: `Maximum amount of storage for a single service instance is 32 Ti.`, + message: `Maximum amount of storage for a single service instance is ${roundDecimal(maxValue.value, 2)} ${maxValue.unit}.`, path: ["profile", "storage"], fatal: true }); diff --git a/apps/deploy-web/src/utils/akash/units.ts b/apps/deploy-web/src/utils/akash/units.ts index 70843a169..358a4c595 100644 --- a/apps/deploy-web/src/utils/akash/units.ts +++ b/apps/deploy-web/src/utils/akash/units.ts @@ -1,14 +1,25 @@ -// https://github.com/akash-network/akash-api/blob/ea71fbd0bee740198034bf1b0261c90baea88be0/go/node/deployment/v1beta3/validation_config.go +//github.com/akash-network/akash-api/blob/d05c262a17178a33e3e5383dcceea384d6260a17/go/node/deployment/v1beta3/validation_config.go +const maxUnitCPU = 384; +const maxUnitGPU = 24; +const maxUnitMemory = 2 * 1024 ** 4; // 2 Ti +const maxUnitStorage = 32 * 1024 ** 4; // 32 Ti +const maxUnitCount = 50; +const maxGroupCount = 20; +const maxGroupUnits = 20; + export const validationConfig = { - maxCpuAmount: 256, - maxGroupCpuCount: 512, - maxGpuAmount: 100, - maxGroupGpuCount: 512, + maxCpuAmount: maxUnitCPU, + maxGroupCpuCount: maxUnitCPU * maxUnitCount, + maxGpuAmount: maxUnitGPU, + maxGroupGpuCount: maxUnitGPU * maxUnitCount, minMemory: 1024, // 1 Mi minStorage: 5 * 1024, // 5 Mi - maxMemory: 512 * 1024 ** 3, // 512 Gi - maxGroupMemory: 1024 * 1024 ** 3, // 1024 Gi - maxStorage: 32 * 1024 ** 4 // 32 Ti + maxMemory: maxUnitMemory, + maxGroupMemory: maxUnitMemory * maxUnitCount, + maxStorage: maxUnitStorage, + maxGroupStorage: maxUnitStorage * maxUnitCount, + maxGroupCount: maxGroupCount, + maxGroupUnits: maxGroupUnits }; export const memoryUnits = [ diff --git a/apps/deploy-web/src/utils/sdl/data.ts b/apps/deploy-web/src/utils/sdl/data.ts index 5354d08e9..d0ceab821 100644 --- a/apps/deploy-web/src/utils/sdl/data.ts +++ b/apps/deploy-web/src/utils/sdl/data.ts @@ -94,6 +94,7 @@ export const SSH_EXPOSE = { export const defaultSshVMService: ServiceType = { ...defaultService, + image: sshVmDistros[0], expose: [] }; diff --git a/apps/deploy-web/tests/deploy-hello-world.spec.ts b/apps/deploy-web/tests/deploy-hello-world.spec.ts index 926e6ddd7..2f7f4a2cc 100644 --- a/apps/deploy-web/tests/deploy-hello-world.spec.ts +++ b/apps/deploy-web/tests/deploy-hello-world.spec.ts @@ -3,6 +3,7 @@ import { setupLeap } from "./fixture/wallet-setup"; import { DeployHelloWorldPage } from "./pages/DeployHelloWorldPage"; test("deploy hello world", async ({ extPage: page, context }) => { + test.setTimeout(300_000); await setupLeap(context, page); const helloWorldPage = new DeployHelloWorldPage(context, page, "new-deployment", "hello-world-card");