From 7261903eceec5080dfe1b097d3090583d5e57beb Mon Sep 17 00:00:00 2001 From: Samuel Rowe Date: Sat, 30 Jul 2022 23:06:54 +0530 Subject: [PATCH] feat(frontend): extended service form utilities to support `build` attribute --- .../components/Modal/service/form-utils.ts | 111 +++++++++++++++++- 1 file changed, 105 insertions(+), 6 deletions(-) diff --git a/services/frontend/src/components/Modal/service/form-utils.ts b/services/frontend/src/components/Modal/service/form-utils.ts index 336cae1..ca2bf9f 100644 --- a/services/frontend/src/components/Modal/service/form-utils.ts +++ b/services/frontend/src/components/Modal/service/form-utils.ts @@ -1,8 +1,28 @@ import type { IEditServiceForm, IServiceNodeItem } from "../../../types"; import * as yup from "yup"; -import { checkArray, pruneArray, pruneObject } from "../../../utils/forms"; +import { + checkArray, + pruneArray, + pruneObject, + extractObjectOrArray, + extractArray, + pruneString +} from "../../../utils/forms"; const initialValues: IEditServiceForm = { + build: { + context: "", + dockerfile: "", + arguments: [], + sshAuthentications: [], + cacheFrom: [], + cacheTo: [], + extraHosts: [], + isolation: "", + labels: [], + sharedMemorySize: "", + target: "" + }, imageName: "", imageTag: "", serviceName: "", @@ -32,6 +52,38 @@ yup.addMethod(yup.string, "port", function (message) { }); export const validationSchema = yup.object({ + build: yup.object({ + context: yup.string().required("Context is required"), + dockerfile: yup.string(), + arguments: yup.array( + yup.object({ + key: yup.string().required("Key is required"), + value: yup.string() + }) + ), + sshAuthentications: yup.object({ + id: yup.string().required("ID is required"), + path: yup.string() + }), + cacheFrom: yup.array(yup.string()), + cacheTo: yup.array(yup.string()), + extraHosts: yup.array( + yup.object({ + hostName: yup.string().required(), + ipAddress: yup.string().required() + }) + ), + isolation: yup.string(), + labels: yup.array( + yup.object({ + key: yup.string().required("Key is required"), + value: yup.string() + }) + ), + // TODO: ? + sharedMemorySize: yup.string(), + target: yup.string() + }), serviceName: yup .string() .max(256, "Service name should be 256 characters or less") @@ -78,7 +130,8 @@ export const validationSchema = yup.object({ ), labels: yup.array( yup.object({ - key: yup.string().required("Key is required") + key: yup.string().required("Key is required"), + value: yup.string() }) ) }); @@ -93,6 +146,7 @@ export const getInitialValues = (node?: IServiceNodeItem): IEditServiceForm => { const { canvasConfig, serviceConfig } = node; const { node_name = "" } = canvasConfig; const { + build, image, container_name = "", environment, @@ -108,7 +162,30 @@ export const getInitialValues = (node?: IServiceNodeItem): IEditServiceForm => { const [imageName, imageTag] = (image ?? ":").split(":"); return { - ...initialValues, + build: build + ? { + context: build.context, + dockerfile: build.dockerfile ?? initialValues.build.dockerfile, + arguments: + extractObjectOrArray("=", "key", "value", build.args) ?? + initialValues.build.arguments, + sshAuthentications: + extractArray("=", "id", "path", build.ssh) ?? + initialValues.build.sshAuthentications, + cacheFrom: build.cache_from ?? initialValues.build.cacheFrom, + cacheTo: build.cache_to ?? initialValues.build.cacheTo, + extraHosts: + extractArray(":", "hostName", "ipAddress", build.extra_hosts) ?? + initialValues.build.extraHosts, + isolation: build.isolation ?? initialValues.build.isolation, + labels: + extractObjectOrArray("=", "key", "value", build.labels) ?? + initialValues.build.labels, + sharedMemorySize: + build.shm_size?.toString() ?? initialValues.build.sharedMemorySize, + target: build.target?.toString() ?? initialValues.build.target + } + : initialValues.build, imageName, imageTag, serviceName: node_name, @@ -157,7 +234,8 @@ export const getFinalValues = ( values: IEditServiceForm, previous?: IServiceNodeItem ): IServiceNodeItem => { - const { environmentVariables, ports, profiles, volumes, labels } = values; + const { build, environmentVariables, ports, profiles, volumes, labels } = + values; return { key: previous?.key ?? "service", @@ -165,11 +243,32 @@ export const getFinalValues = ( position: previous?.position ?? { left: 0, top: 0 }, inputs: previous?.inputs ?? ["op_source"], outputs: previous?.outputs ?? [], - config: (previous as any)?.config ?? {}, canvasConfig: { node_name: values.serviceName }, serviceConfig: { + build: pruneObject({ + context: build.context, + dockerfile: pruneString(build.dockerfile), + args: pruneObject(build.arguments), + ssh: pruneArray( + build.sshAuthentications.map((authentication) => + [authentication.id, authentication.path].join("=") + ) + ), + cache_from: pruneArray(build.cacheFrom), + cache_to: pruneArray(build.cacheTo), + extra_hosts: pruneArray( + build.extraHosts.map((extraHost) => + [extraHost.hostName, extraHost.ipAddress].join(":") + ) + ), + isolation: pruneString(build.isolation), + labels: pruneObject(build.labels), + // NOTE: This could be a potential bug for "0". + shm_size: pruneString(build.sharedMemorySize), + target: pruneString(build.target) + }), image: `${values.imageName}${ values.imageTag ? `:${values.imageTag}` : "" }`, @@ -199,5 +298,5 @@ export const getFinalValues = ( Object.fromEntries(labels.map((label) => [label.key, label.value])) ) } - } as any; + }; };