Merge pull request #81 from nuxxapp/fix/final-value-gen

Fix bugs in final value generation
pull/83/head
Artem Golub 3 years ago committed by GitHub
commit 0e38a33b83
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -1,5 +1,11 @@
import * as yup from "yup"; import * as yup from "yup";
import { IEditNetworkForm, INetworkNodeItem } from "../../../types"; import {
IEditNetworkForm,
IIPAM,
INetworkNodeItem,
IPAMConfig
} from "../../../types";
import { pruneArray, pruneObject } from "../../../utils/forms";
export const validationSchema = yup.object({ export const validationSchema = yup.object({
entryName: yup entryName: yup
@ -12,10 +18,7 @@ export const validationSchema = yup.object({
.max(256, "Network name should be 256 characters or less") .max(256, "Network name should be 256 characters or less")
.required("Network name is required"), .required("Network name is required"),
driver: yup driver: yup.string().max(256, "Driver should be 256 characters or less"),
.string()
.max(256, "Driver should be 256 characters or less")
.default("default"),
configurations: yup.array( configurations: yup.array(
yup.object({ yup.object({
@ -70,7 +73,7 @@ export const tabs = [
export const initialValues: IEditNetworkForm = { export const initialValues: IEditNetworkForm = {
entryName: "", entryName: "",
networkName: "", networkName: "",
driver: "default", driver: "",
configurations: [], configurations: [],
options: [], options: [],
labels: [] labels: []
@ -93,30 +96,29 @@ export const getInitialValues = (node?: INetworkNodeItem): IEditNetworkForm => {
networkName: name, networkName: name,
driver: ipam?.driver ?? "", driver: ipam?.driver ?? "",
configurations: configurations:
ipam?.config.map((item) => ({ ipam?.config?.map((item) => ({
subnet: item.subnet, subnet: item.subnet ?? "",
ipRange: item.ip_range, ipRange: item.ip_range ?? "",
gateway: item.gateway, gateway: item.gateway ?? "",
auxAddresses: Object.entries(item.aux_addresses).map( auxAddresses: Object.entries(item.aux_addresses ?? []).map(
([hostName, ipAddress]) => ({ ([hostName, ipAddress]) => ({
hostName, hostName,
ipAddress ipAddress
}) })
) )
})) ?? [], })) ?? [],
options: Object.keys(ipam?.options || {}).map((key) => { options: Object.keys(ipam?.options ?? {}).map((key) => {
if (!ipam) {
throw new Error("Control should not reach here.");
}
return { return {
key, key,
value: ipam.options[key].toString() value: ipam?.options?.[key].toString() ?? ""
}; };
}), }),
labels: Object.entries(labels as any).map(([key, value]: any) => ({ labels: labels
? Object.entries(labels as any).map(([key, value]: any) => ({
key, key,
value value
})) }))
: []
}; };
}; };
@ -129,34 +131,63 @@ export const getFinalValues = (
return { return {
key: previous?.key ?? "network", key: previous?.key ?? "network",
type: "NETWORK", type: "NETWORK",
position: {
left: 0,
top: 0
},
inputs: previous?.inputs ?? [], inputs: previous?.inputs ?? [],
outputs: previous?.outputs ?? [], outputs: previous?.outputs ?? [],
config: (previous as any)?.config ?? {},
canvasConfig: { canvasConfig: {
node_name: values.entryName node_name: values.entryName
}, },
networkConfig: { networkConfig: {
name: values.networkName, name: values.networkName,
ipam: { ipam: pruneObject({
driver, driver: driver ? driver : undefined,
config: configurations.map((configuration) => ({ config: pruneArray(
subnet: configuration.subnet, configurations.map((configuration) =>
ip_range: configuration.ipRange, pruneObject({
gateway: configuration.gateway, subnet: configuration.subnet ? configuration.subnet : undefined,
aux_addresses: Object.fromEntries( ip_range: configuration.ipRange
? configuration.ipRange
: undefined,
gateway: configuration.gateway
? configuration.gateway
: undefined,
aux_addresses: (() => {
if (configuration.auxAddresses.length === 0) {
return undefined;
}
/* We do not have to worry about empty `hostName` and `ipAddress`
* values because Yup would report such values as error.
*/
return Object.fromEntries(
configuration.auxAddresses.map((auxAddress) => [ configuration.auxAddresses.map((auxAddress) => [
auxAddress.hostName, auxAddress.hostName,
auxAddress.ipAddress auxAddress.ipAddress
]) ])
);
})()
})
) )
})), ) as IPAMConfig[],
options: Object.fromEntries( options: (() => {
if (options.length === 0) {
return undefined;
}
/* We do not have to worry about empty `key` and `value`
* values because Yup would report such values as error.
*/
return Object.fromEntries(
options.map((option) => [option.key, option.value]) options.map((option) => [option.key, option.value])
) );
}, })()
labels: Object.fromEntries( }) as IIPAM,
labels.map((label) => [label.key, label.value]) labels: pruneObject(
) Object.fromEntries(labels.map((label) => [label.key, label.value]))
) as Record<string, string>
} }
} as any; };
}; };

@ -1,7 +1,6 @@
import type { IEditServiceForm, IServiceNodeItem } from "../../../types"; import type { IEditServiceForm, IServiceNodeItem } from "../../../types";
import * as yup from "yup"; import * as yup from "yup";
import lodash from "lodash"; import { checkArray, pruneArray, pruneObject } from "../../../utils/forms";
import { checkArray } from "../../../utils/forms";
const initialValues: IEditServiceForm = { const initialValues: IEditServiceForm = {
imageName: "", imageName: "",
@ -95,10 +94,9 @@ export const getInitialValues = (node?: IServiceNodeItem): IEditServiceForm => {
labels labels
} = serviceConfig; } = serviceConfig;
const environment0: string[] = checkArray(environment, "environment"); const environment0: string[] = checkArray(environment || [], "environment");
const volumes0: string[] = checkArray(volumes, "volumes"); const volumes0: string[] = checkArray(volumes, "volumes");
const ports0: string[] = checkArray(ports, "ports"); const ports0: string[] = checkArray(ports, "ports");
const labels0: string[] = checkArray(labels, "labels");
const [imageName, imageTag] = (image ?? ":").split(":"); const [imageName, imageTag] = (image ?? ":").split(":");
return { return {
@ -137,13 +135,12 @@ export const getInitialValues = (node?: IServiceNodeItem): IEditServiceForm => {
return { hostPort, containerPort, protocol } as any; return { hostPort, containerPort, protocol } as any;
}), }),
labels: labels0.map((label) => { labels: labels
const [key, value] = label.split("="); ? Object.entries(labels as any).map(([key, value]: any) => ({
return {
key, key,
value value
}; }))
}) : []
}; };
}; };
@ -153,15 +150,13 @@ export const getFinalValues = (
): IServiceNodeItem => { ): IServiceNodeItem => {
const { environmentVariables, ports, volumes, labels } = values; const { environmentVariables, ports, volumes, labels } = values;
return lodash.mergeWith( return {
lodash.cloneDeep(previous) || { key: previous?.key ?? "service",
key: "service",
type: "SERVICE", type: "SERVICE",
inputs: ["op_source"], position: previous?.position ?? { left: 0, top: 0 },
outputs: [], inputs: previous?.inputs ?? ["op_source"],
config: {} outputs: previous?.outputs ?? [],
}, config: (previous as any)?.config ?? {},
{
canvasConfig: { canvasConfig: {
node_name: values.serviceName node_name: values.serviceName
}, },
@ -170,9 +165,11 @@ export const getFinalValues = (
values.imageTag ? `:${values.imageTag}` : "" values.imageTag ? `:${values.imageTag}` : ""
}`, }`,
container_name: values.containerName, container_name: values.containerName,
environment: environmentVariables.map( environment: pruneArray(
environmentVariables.map(
(variable) => (variable) =>
`${variable.key}${variable.value ? `=${variable.value}` : ""}` `${variable.key}${variable.value ? `=${variable.value}` : ""}`
)
), ),
volumes: volumes.length volumes: volumes.length
? volumes.map( ? volumes.map(
@ -188,16 +185,9 @@ export const getFinalValues = (
(port.containerPort ? `:${port.containerPort}` : "") + (port.containerPort ? `:${port.containerPort}` : "") +
(port.protocol ? `/${port.protocol}` : "") (port.protocol ? `/${port.protocol}` : "")
), ),
labels: labels.map( labels: pruneObject(
(label) => `${label.key}${label.value ? `=${label.value}` : ""}` Object.fromEntries(labels.map((label) => [label.key, label.value]))
) )
} }
}, } as any;
(obj, src) => {
if (!lodash.isNil(src)) {
return src;
}
return obj;
}
) as any;
}; };

@ -1,7 +1,6 @@
import lodash from "lodash";
import * as yup from "yup"; import * as yup from "yup";
import { IEditVolumeForm, IVolumeNodeItem } from "../../../types"; import { IEditVolumeForm, IVolumeNodeItem } from "../../../types";
import { checkArray } from "../../../utils/forms"; import { pruneObject } from "../../../utils/forms";
export const validationSchema = yup.object({ export const validationSchema = yup.object({
entryName: yup entryName: yup
@ -36,19 +35,16 @@ export const getInitialValues = (node?: IVolumeNodeItem): IEditVolumeForm => {
const { node_name = "" } = canvasConfig; const { node_name = "" } = canvasConfig;
const { name = "", labels } = volumeConfig; const { name = "", labels } = volumeConfig;
const labels0: string[] = checkArray(labels, "labels");
return { return {
...initialValues, ...initialValues,
entryName: node_name, entryName: node_name,
volumeName: name, volumeName: name,
labels: labels0.map((label) => { labels: labels
const [key, value] = label.split("="); ? Object.entries(labels as any).map(([key, value]: any) => ({
return {
key, key,
value value
}; }))
}) : []
}; };
}; };
@ -58,32 +54,22 @@ export const getFinalValues = (
): IVolumeNodeItem => { ): IVolumeNodeItem => {
const { labels } = values; const { labels } = values;
return lodash.mergeWith( return {
lodash.cloneDeep(previous) || { key: previous?.key ?? "volume",
key: "volume",
type: "VOLUME", type: "VOLUME",
inputs: [], position: previous?.position ?? { left: 0, top: 0 },
outputs: [], inputs: previous?.inputs ?? [],
config: {} outputs: previous?.outputs ?? [],
},
{
canvasConfig: { canvasConfig: {
node_name: values.entryName node_name: values.entryName
}, },
volumeConfig: { volumeConfig: {
name: values.volumeName, name: values.volumeName,
labels: labels.map( labels: pruneObject(
(label) => `${label.key}${label.value ? `=${label.value}` : ""}` Object.fromEntries(labels.map((label) => [label.key, label.value]))
) ) as Record<string, string>
}
},
(obj, src) => {
if (!lodash.isNil(src)) {
return src;
}
return obj;
} }
) as any; };
}; };
export const tabs = [ export const tabs = [

@ -78,31 +78,31 @@ export interface IVolumeTopLevel {
device: string; device: string;
}; };
external: boolean; external: boolean;
labels: string[] | KeyValuePair; labels?: string[] | KeyValuePair;
name: string; name: string;
} }
export interface IPAMConfig {
subnet?: string;
ip_range?: string;
gateway?: string;
aux_addresses?: Record<string, string>;
}
export interface IIPAM {
driver?: string;
config?: IPAMConfig[];
options?: Record<string, string>;
}
export interface INetworkTopLevel { export interface INetworkTopLevel {
driver: string; driver: string;
driver_opts: KeyValPair; driver_opts: KeyValPair;
attachable: boolean; attachable: boolean;
enable_ipv6: boolean; enable_ipv6: boolean;
ipam: { ipam?: IIPAM;
driver: string;
config: {
subnet: string;
ip_range: string;
gateway: string;
aux_addresses: {
host1: string;
host2: string;
host3: string;
};
}[];
options: KeyValPair;
};
internal: boolean; internal: boolean;
labels: string[] | KeyValPair; labels?: string[] | KeyValPair;
external: boolean; external: boolean;
name: string; name: string;
} }

@ -1,3 +1,5 @@
import lodash from "lodash";
export const checkArray = <T>(array: any, name: string): T => { export const checkArray = <T>(array: any, name: string): T => {
if (!Array.isArray(array)) { if (!Array.isArray(array)) {
throw new Error( throw new Error(
@ -6,3 +8,19 @@ export const checkArray = <T>(array: any, name: string): T => {
} }
return array as unknown as T; return array as unknown as T;
}; };
export const pruneArray = <T>(array: (T | undefined)[]): T[] | undefined => {
const result = array.filter(Boolean);
if (array.length === 0) {
return undefined;
}
return result as T[];
};
export const pruneObject = <T>(object: T): unknown | undefined => {
const result = lodash.pickBy(object ?? {}, (value) => value !== undefined);
if (Object.keys(result).length === 0) {
return undefined;
}
return result as unknown;
};

Loading…
Cancel
Save