deployment config

This commit is contained in:
mbecker20
2022-03-19 14:59:36 -07:00
parent 9c09d10352
commit 048905997a
13 changed files with 234 additions and 29 deletions
+1 -1
View File
@@ -8,7 +8,7 @@
"node": ">=10"
},
"scripts": {
"start": "yarn build && build/monitor-cli.js",
"start": "yarn build && build/monitor-cli.js --help",
"build": "vite build && node post-build.mjs && chmod +x build/monitor-cli.js",
"publish-cli": "yarn build && cd build && npm publish --access=public && node update-version.mjs"
},
+2
View File
@@ -28,3 +28,5 @@
* periphery
* install
+11 -12
View File
@@ -1,5 +1,5 @@
import React, { ReactNode, useState } from "react";
import { Newline, render, Text, useInput, Box } from "ink";
import { Newline, render, Text, Box } from "ink";
import init from "./util/init";
import Intro from "./components/Intro";
import Docker from "./components/docker/Docker";
@@ -7,32 +7,30 @@ import Periphery from "./components/Periphery";
import Confirm from "./components/Confirm";
import { createUseConfig, createUseSequence } from "./util/state";
import { Config } from "./types";
import DeploymentConfig from "./components/deployment-config/DeploymentConfig";
export const useMainSequence = createUseSequence();
export const useConfig = createUseConfig<Config>({});
init().then(({ flags, dockerInstalled }) => {
const App = () => {
const { current, next, prev } = useMainSequence();
const { current, next } = useMainSequence();
const [periphery, setPeriphery] = useState<boolean | undefined>(
flags.core ? true : flags.periphery ? false : undefined
);
const [installing, setInstalling] = useState(false);
useInput((_, key) => {
if (!installing && key.escape) prev();
});
const corePages: ReactNode[] = periphery === false ? [] : [];
const peripheryPages: ReactNode[] = periphery ? [] : [];
const pages: ReactNode[] = [
<Intro />,
...(dockerInstalled ? [] : [<Docker />]),
...(!flags.core && !flags.periphery
? [<Periphery setPeriphery={setPeriphery} />]
: []),
dockerInstalled ? undefined : <Docker />,
<DeploymentConfig deployment="mongo-db" onFinish={next} />,
!flags.core && !flags.periphery
? <Periphery setPeriphery={setPeriphery} />
: undefined,
...(periphery === true ? peripheryPages : []),
...(periphery === false ? corePages : []),
<Confirm
@@ -41,12 +39,13 @@ init().then(({ flags, dockerInstalled }) => {
next();
}}
/>,
];
].filter(val => val ? true : false);
return (
<Box flexDirection="column">
<Newline />
<Text color="blue" bold underline>
monitor CLI
Monitor CLI
</Text>
<Newline />
{pages[current]}
+1 -1
View File
@@ -2,7 +2,7 @@ import React from "react";
import { Box } from "ink";
import { Config, SetConfig } from "../types";
const Mongo = ({}: { config: Config; setConfig: SetConfig; }) => {
const Mongo = () => {
return (
<Box>
+1 -1
View File
@@ -22,7 +22,7 @@ const Periphery = ({
setPeriphery(item === "periphery");
next();
}}
direction="vertical"
vertical
/>
);
};
+9 -1
View File
@@ -1,7 +1,15 @@
import React from "react";
import { Box } from "ink";
import { useConfig, useMainSequence } from "../cli";
import { createUseSequence } from "../util/state";
const Registry = ({}: {}) => {
const useRegisterySequence = createUseSequence();
const Registry = () => {
const { prev } = useMainSequence();
const { current } = useRegisterySequence();
const { config, set } = useConfig();
return (
<Box>
@@ -0,0 +1,158 @@
import React, { Fragment, useState } from "react";
import { Box, Newline, Text } from "ink";
import TextInput from "ink-text-input";
import { useEsc, useStore } from "../../util/hooks";
import { useMainSequence } from "../../cli";
import EnterToContinue from "../util/EnterToContinue";
import LabelledSelector from "../util/LabelledSelector";
import YesNo from "../util/YesNo";
type DeploymentConfig = {
stage: "name" | "port" | "volume" | "restart" | "confirm";
name: string;
port?: string;
volume?: string | false;
restart?: string;
};
const RESTART_MODES = ["no", "on-failure", "always", "unless-stopped"];
const DeploymentConfig = ({
deployment,
onFinish,
}: {
deployment: "mongo-db" | "registry";
onFinish: (config: DeploymentConfig) => void;
}) => {
const [config, setConfig, setMany] = useStore<DeploymentConfig>({
stage: "name",
name: deployment,
});
const { stage, name, port, volume, restart } = config;
const { next } = useMainSequence();
useEsc(() => {
switch (stage) {
case "port":
setConfig("stage", "name");
break;
case "volume":
setMany(["stage", "port"], ["volume", undefined]);
break;
case "restart":
setMany(["stage", "volume"], ["volume", undefined]);
break;
case "confirm":
setMany(["stage", "restart"], ["restart", undefined]);
break;
}
});
return (
<Box flexDirection="column">
<Text color="green">
name:{" "}
<Text color="white">
{stage === "name" ? (
<TextInput
value={name}
onChange={(name) => setConfig("name", name)}
onSubmit={(name) => {
// setConfig("port", deployment === "mongo-db" ? "27017" : "5000");
setMany(["name", name], ["stage", "port"]);
}}
/>
) : (
name
)}
</Text>
</Text>
{stage === "port" && (
<Text color="green">
port:{" "}
<Text color="white">
<TextInput
value={port || (deployment === "mongo-db" ? "27017" : "5000")}
onChange={(port) => setConfig("port", port)}
onSubmit={(port) => {
setMany(["stage", "volume"], ["port", port]);
}}
/>
</Text>
</Text>
)}
{port && stage !== "port" && (
<Text color="green">
port: <Text color="white">{port}</Text>
</Text>
)}
{stage === "volume" && volume === undefined && (
<YesNo
label={
<Text>
mount data on local filesystem? this is used to{" "}
<Text color="green">persist data</Text> between{" "}
<Text color="green">container restarts</Text>.
</Text>
}
onSelect={(use) => {
if (use === "yes") {
setConfig("volume", `~/${name}`);
} else {
setMany(["stage", "restart"], ["volume", false]);
}
}}
vertical
/>
)}
{volume !== undefined && (
<Text color="green">
mount folder:{" "}
<Text color="white">
{stage === "volume" ? (
<TextInput
value={volume as string}
onChange={(volume) => setConfig("volume", volume)}
onSubmit={(volume) => {
setMany(["stage", "restart"], ["volume", volume]);
}}
/>
) : (
volume || "no"
)}
</Text>
</Text>
)}
{stage === "restart" && (
<LabelledSelector
label="restart: "
items={RESTART_MODES}
onSelect={(restart) => {
setMany(["stage", "confirm"], ["restart", restart]);
}}
/>
)}
{restart && (
<Text color="green">
restart: <Text color="white">{restart}</Text>
</Text>
)}
{stage === "confirm" && (
<Fragment>
<Newline />
<EnterToContinue onEnter={() => onFinish(config)} />
</Fragment>
)}
</Box>
);
};
export default DeploymentConfig;
+6 -1
View File
@@ -3,15 +3,20 @@ import { Newline, Text } from "ink";
import YesNo from "../util/YesNo";
import InstallDocker from "./InstallDocker";
import { useMainSequence } from "../../cli";
import { useEsc } from "../../util/hooks";
const Docker = () => {
const { next } = useMainSequence();
const { next, prev } = useMainSequence();
const [installDocker, setInstallDocker] = useState<boolean>();
useEffect(() => {
if (installDocker === false) {
process.exit();
}
}, [installDocker]);
useEsc(prev);
if (installDocker === undefined) {
return (
<YesNo
+2 -2
View File
@@ -2,7 +2,7 @@ import React from "react";
import { Text } from "ink";
import { useEnter } from "../../util/hooks";
const EnterToContinue = ({ onEnter }: { onEnter: () => void }) => {
const EnterToContinue = ({ onEnter, pressEnterTo }: { onEnter: () => void; pressEnterTo?: string }) => {
useEnter(onEnter);
return (
<Text>
@@ -10,7 +10,7 @@ const EnterToContinue = ({ onEnter }: { onEnter: () => void }) => {
<Text color="green" bold>
enter
</Text>{" "}
to continue.
to {pressEnterTo || "continue"}.
</Text>
);
};
+10 -6
View File
@@ -6,19 +6,23 @@ const LabelledSelector = ({
label,
items,
onSelect,
direction = "horizontal",
labelColor = "green"
vertical,
labelColor = "white",
}: {
label: ReactNode;
labelColor?: "green" | "white";
items: string[];
onSelect?: (item: string, index: number) => void;
direction?: "vertical" | "horizontal"
vertical?: boolean;
}) => {
return (
<Box flexDirection={direction === "horizontal" ? "row" : "column"}>
{typeof label === "string" ? <Text color={labelColor}>{label} </Text> : label}
{direction === "vertical" && <Newline />}
<Box flexDirection={vertical ? "column" : "row"}>
{typeof label === "string" ? (
<Text color={labelColor}>{label} </Text>
) : (
label
)}
{vertical && <Newline />}
<Selector items={items} onSelect={onSelect} />
</Box>
);
+3 -3
View File
@@ -6,7 +6,7 @@ const YesNo = ({
onYes,
onNo,
onSelect,
direction,
vertical,
labelColor,
noYes
}: {
@@ -14,7 +14,7 @@ const YesNo = ({
onYes?: () => void;
onNo?: () => void;
onSelect?: (res: "yes" | "no") => void;
direction?: "vertical" | "horizontal";
vertical?: boolean;
labelColor?: "green" | "white";
noYes?: boolean;
}) => {
@@ -30,7 +30,7 @@ const YesNo = ({
}
onSelect && onSelect(item as "yes" | "no");
}}
direction={direction}
vertical={vertical}
labelColor={labelColor}
/>
);
+1
View File
@@ -0,0 +1 @@
export const DEFAULT_PORT = 9000;
+29 -1
View File
@@ -24,4 +24,32 @@ export function useEnter(onEnter: () => void) {
export function useEsc(onEsc: () => void) {
useKey("escape", onEsc);
}
}
export function useStore<T>(
init: T
): [
T,
(field: keyof T, val: T[keyof T]) => void,
(...updates: Array<[field: keyof T, val: T[keyof T]]>) => void
] {
const [store, setStore] = useState(init);
const set = useCallback((field: keyof T, val: T[keyof T]) => {
setStore((store) => ({ ...store, [field]: val }));
}, []);
const setMany = useCallback(
(...updates: Array<[field: keyof T, val: T[keyof T]]>) => {
setStore((store) =>
Object.assign(
{},
store,
...updates.map(([field, val]) => ({ [field]: val }))
)
);
},
[]
);
return [store, set, setMany];
}