mirror of https://github.com/ctk-hq/ctk
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
193 lines
5.1 KiB
TypeScript
193 lines
5.1 KiB
TypeScript
import type { IEditServiceForm, IServiceNodeItem } from "../../../types";
|
|
import * as yup from "yup";
|
|
import lodash from "lodash";
|
|
import { checkArray } from "../../../utils/forms";
|
|
|
|
const initialValues: IEditServiceForm = {
|
|
imageName: "",
|
|
imageTag: "",
|
|
serviceName: "",
|
|
containerName: "",
|
|
ports: [],
|
|
environmentVariables: [],
|
|
volumes: [],
|
|
labels: []
|
|
};
|
|
|
|
yup.addMethod<yup.StringSchema>(yup.string, "port", function (message) {
|
|
return this.test("test-port", message, function (value):
|
|
| boolean
|
|
| yup.ValidationError {
|
|
const { path, createError } = this;
|
|
|
|
if (value) {
|
|
const result = parseInt(value, 10);
|
|
if (isNaN(result) || result < 0 || result > 65535) {
|
|
return createError({ path, message });
|
|
}
|
|
}
|
|
|
|
return true;
|
|
});
|
|
});
|
|
|
|
export const validationSchema = yup.object({
|
|
serviceName: yup
|
|
.string()
|
|
.max(256, "Service name should be 256 characters or less")
|
|
.required("Service name is required"),
|
|
imageName: yup
|
|
.string()
|
|
.max(256, "Image name should be 256 characters or less")
|
|
.required("Image name is required"),
|
|
imageTag: yup.string().max(256, "Image tag should be 256 characters or less"),
|
|
containerName: yup
|
|
.string()
|
|
.max(256, "Container name should be 256 characters or less")
|
|
.required("Container name is required"),
|
|
ports: yup.array(
|
|
yup.object({
|
|
hostPort: (yup.string().required("Host port is required") as any).port(
|
|
"Host port should be an integer in the range 0-65535"
|
|
),
|
|
containerPort: (yup.string() as any).port(
|
|
"Container port should be an integer in the range 0-65535"
|
|
),
|
|
protocol: yup
|
|
.string()
|
|
.oneOf(["tcp", "udp"], "Protocol should be tcp or udp")
|
|
})
|
|
),
|
|
environmentVariables: yup.array(
|
|
yup.object({
|
|
key: yup.string().required("Key is required"),
|
|
value: yup.string().required("Value is required")
|
|
})
|
|
),
|
|
volumes: yup.array(
|
|
yup.object({
|
|
name: yup.string().required("Name is required"),
|
|
containerPath: yup.string(),
|
|
accessMode: yup.string()
|
|
})
|
|
),
|
|
labels: yup.array(
|
|
yup.object({
|
|
key: yup.string().required("Key is required"),
|
|
value: yup.string().required("Value is required")
|
|
})
|
|
)
|
|
});
|
|
|
|
export const getInitialValues = (node?: IServiceNodeItem): IEditServiceForm => {
|
|
if (!node) {
|
|
return {
|
|
...initialValues
|
|
};
|
|
}
|
|
|
|
const { canvasConfig, serviceConfig } = node;
|
|
const { node_name = "" } = canvasConfig;
|
|
const {
|
|
image,
|
|
container_name = "",
|
|
environment,
|
|
volumes,
|
|
ports,
|
|
labels
|
|
} = serviceConfig;
|
|
|
|
const environment0: string[] = checkArray(environment, "environment");
|
|
const volumes0: string[] = checkArray(volumes, "volumes");
|
|
const ports0: string[] = checkArray(ports, "ports");
|
|
const labels0: string[] = checkArray(labels, "labels");
|
|
const [imageName, imageTag] = (image ?? ":").split(":");
|
|
|
|
return {
|
|
...initialValues,
|
|
imageName,
|
|
imageTag,
|
|
serviceName: node_name,
|
|
containerName: container_name,
|
|
environmentVariables: environment0.map((variable) => {
|
|
const [key, value] = variable.split(":");
|
|
return {
|
|
key,
|
|
value
|
|
};
|
|
}),
|
|
volumes: volumes0.map((volume) => {
|
|
const [name, containerPath, accessMode] = volume.split(":");
|
|
return {
|
|
name,
|
|
containerPath,
|
|
accessMode
|
|
};
|
|
}),
|
|
ports: ports0.map((port) => {
|
|
const slashIndex = port.lastIndexOf("/");
|
|
const protocol = slashIndex >= 0 ? port.substring(slashIndex + 1) : "";
|
|
const [hostPort, containerPort] = port
|
|
.substring(0, slashIndex)
|
|
.split(":");
|
|
|
|
if (!["tcp", "udp"].includes(protocol)) {
|
|
throw new Error(
|
|
`Invalid protocol "${protocol}" found while deserializing.`
|
|
);
|
|
}
|
|
|
|
return { hostPort, containerPort, protocol } as any;
|
|
}),
|
|
labels: labels0.map((label) => {
|
|
const [key, value] = label.split(":");
|
|
return {
|
|
key,
|
|
value
|
|
};
|
|
})
|
|
};
|
|
};
|
|
|
|
export const getFinalValues = (
|
|
values: IEditServiceForm,
|
|
previous?: IServiceNodeItem
|
|
): IServiceNodeItem => {
|
|
const { environmentVariables, ports, volumes, labels } = values;
|
|
|
|
return lodash.merge(
|
|
lodash.cloneDeep(previous) || {
|
|
key: "service",
|
|
type: "SERVICE",
|
|
inputs: ["op_source"],
|
|
outputs: [],
|
|
config: {}
|
|
},
|
|
{
|
|
canvasConfig: {
|
|
node_name: values.serviceName
|
|
},
|
|
serviceConfig: {
|
|
image: `${values.imageName}:${values.imageTag}`,
|
|
container_name: values.containerName,
|
|
environment: environmentVariables.map(
|
|
(variable) => `${variable.key}:${variable.value}`
|
|
),
|
|
volumes: volumes.map(
|
|
(volume) =>
|
|
volume.name +
|
|
(volume.containerPath ? `:${volume.containerPath}` : "") +
|
|
(volume.accessMode ? `:${volume.accessMode}` : "")
|
|
),
|
|
ports: ports.map(
|
|
(port) =>
|
|
port.hostPort +
|
|
(port.containerPort ? `:${port.containerPort}` : "") +
|
|
(port.protocol ? `/${port.protocol}` : "")
|
|
),
|
|
labels: labels.map((label) => `${label.key}:${label.value}`)
|
|
}
|
|
}
|
|
) as any;
|
|
};
|