mirror of
https://github.com/moghtech/komodo.git
synced 2026-09-05 16:00:50 +00:00
begin cli v2
This commit is contained in:
@@ -1,62 +0,0 @@
|
||||
import React, { ReactNode, useState } from "react";
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import FinalConfig from "./components/FinalConfig";
|
||||
import { useConfig, useSequence } from "./hooks";
|
||||
import { Config } from "./types";
|
||||
import Intro from "./components/Intro";
|
||||
import Setup from "./components/Setup";
|
||||
import Periphery from "./components/Periphery";
|
||||
import Mongo from "./components/mongo/Mongo";
|
||||
import { dockerNotInstalled } from "./monitor-cli";
|
||||
import Docker from "./components/docker/Docker";
|
||||
import Registry from "./components/registry/Registry";
|
||||
|
||||
const App = () => {
|
||||
const [current, next, prev] = useSequence();
|
||||
const [periphery, setPeriphery] = useState<boolean>();
|
||||
const [installing, setInstalling] = useState(false);
|
||||
const [config, setConfig] = useConfig<Config>({
|
||||
mongoURL: "",
|
||||
registryURL: "",
|
||||
});
|
||||
|
||||
const corePages: ReactNode[] = [
|
||||
<Mongo setConfig={setConfig} next={next} />,
|
||||
<Registry setConfig={setConfig} next={next} />,
|
||||
];
|
||||
|
||||
const peripheryPages: ReactNode[] = [];
|
||||
|
||||
const pages: ReactNode[] = [
|
||||
<Intro next={next} />,
|
||||
...(dockerNotInstalled ? [<Docker next={next} />] : []),
|
||||
<Periphery setPeriphery={setPeriphery} next={next} />,
|
||||
...(periphery === true ? peripheryPages : []),
|
||||
...(periphery === false ? corePages : []),
|
||||
<FinalConfig
|
||||
periphery={periphery}
|
||||
config={config}
|
||||
onConfirm={() => {
|
||||
next();
|
||||
setInstalling(true);
|
||||
}}
|
||||
/>,
|
||||
<Setup periphery={periphery} />,
|
||||
];
|
||||
|
||||
useInput((_, key) => {
|
||||
if (!installing && key.escape) prev();
|
||||
});
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Newline />
|
||||
<Text color="blue" bold underline>
|
||||
Monitor CLI
|
||||
</Text>
|
||||
<Newline />
|
||||
{pages[current]}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
@@ -0,0 +1,14 @@
|
||||
import React from "react";
|
||||
import { render } from "ink";
|
||||
import { Box } from "ink";
|
||||
import { checkDockerNotInstalled } from "./helpers/docker";
|
||||
|
||||
const App = () => {
|
||||
return <Box></Box>;
|
||||
};
|
||||
|
||||
export let dockerNotInstalled = true;
|
||||
checkDockerNotInstalled().then((res) => {
|
||||
dockerNotInstalled = res;
|
||||
render(<App />);
|
||||
});
|
||||
@@ -1,53 +0,0 @@
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import React from "react";
|
||||
import { Config } from "../types";
|
||||
|
||||
const FinalConfig = (p: {
|
||||
periphery: boolean | undefined;
|
||||
config: Config;
|
||||
onConfirm: () => void;
|
||||
}) => {
|
||||
useInput((_, key) => {
|
||||
if (key.return) p.onConfirm();
|
||||
});
|
||||
if (p.periphery) {
|
||||
return (
|
||||
<Text>
|
||||
press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to start setup of the <Text color="red">monitor periphery</Text>. you
|
||||
cannot go back after this begins.
|
||||
</Text>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text color="blue" bold>
|
||||
your monitor core config
|
||||
</Text>
|
||||
<Newline />
|
||||
<Box flexDirection="column" borderColor="green" borderStyle="round">
|
||||
<Text color="green">
|
||||
mongo url: <Text color="white">{p.config.mongoURL}</Text>
|
||||
</Text>
|
||||
<Text color="green">
|
||||
registry url: <Text color="white">{p.config.registryURL}</Text>
|
||||
</Text>
|
||||
</Box>
|
||||
<Newline />
|
||||
<Text>
|
||||
press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to start setup of <Text color="cyan">monitor core</Text>. you cannot
|
||||
go back after this begins.
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default FinalConfig;
|
||||
@@ -1,29 +0,0 @@
|
||||
import React from "react";
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
|
||||
const Intro = (p: { next: () => void }) => {
|
||||
useInput((_, key) => {
|
||||
if (key.return) p.next();
|
||||
});
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>
|
||||
This is a CLI to setup{" "}
|
||||
<Text color="cyan" bold>
|
||||
Monitor
|
||||
</Text>
|
||||
, a tool to manage application deployment.
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text>
|
||||
press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to continue.
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Intro;
|
||||
@@ -1,28 +0,0 @@
|
||||
import React from "react";
|
||||
import { Box, Newline, Text } from "ink";
|
||||
import Selector from "./util/Selector";
|
||||
import { SetConfig } from "../types";
|
||||
|
||||
const Periphery = (p: {
|
||||
setPeriphery: (a: boolean) => void;
|
||||
next: () => void;
|
||||
}) => {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>
|
||||
Are you setting up <Text color="cyan">monitor core</Text> or {" "}
|
||||
<Text color="red">monitor periphery</Text>?
|
||||
</Text>
|
||||
<Newline />
|
||||
<Selector
|
||||
items={["core", "peripheral"]}
|
||||
onSelect={(item) => {
|
||||
p.setPeriphery(item === "periphery");
|
||||
p.next();
|
||||
}}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Periphery;
|
||||
@@ -1,18 +0,0 @@
|
||||
import React from "react";
|
||||
import { Box, Text } from "ink";
|
||||
|
||||
const Setup = (p: { periphery: boolean | undefined }) => {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text>
|
||||
setting up{" "}
|
||||
<Text color={p.periphery ? "red" : "cyan"}>
|
||||
{p.periphery ? "a peripheral client..." : "monitor core"}
|
||||
</Text>{" "}
|
||||
{!p.periphery && "using the specified configuration..."}
|
||||
</Text>
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default Setup;
|
||||
@@ -1,40 +0,0 @@
|
||||
import React, { useEffect, useState } from "react";
|
||||
import { Text } from "ink";
|
||||
import { Next } from "../../types";
|
||||
import YesNo from "../util/YesNo";
|
||||
import InstallDocker from "./InstallDocker";
|
||||
|
||||
const Docker = ({ next }: { next: Next }) => {
|
||||
const [installDocker, setInstallDocker] = useState<boolean>();
|
||||
useEffect(() => {
|
||||
if (installDocker === false) {
|
||||
process.exit();
|
||||
}
|
||||
}, [installDocker]);
|
||||
if (installDocker === undefined) {
|
||||
return (
|
||||
<YesNo
|
||||
label={
|
||||
<Text>
|
||||
Docker does not appear to be installed. Would you like to install
|
||||
Docker? This will begin the{" "}
|
||||
<Text color="cyan" bold>
|
||||
Docker Install Helper
|
||||
</Text>{" "}
|
||||
and is necessary to proceed.
|
||||
</Text>
|
||||
}
|
||||
onSelect={(res) => {
|
||||
setInstallDocker(res === "yes");
|
||||
}}
|
||||
direction="vertical"
|
||||
/>
|
||||
);
|
||||
} else if (installDocker) {
|
||||
return <InstallDocker next={next} />;
|
||||
} else {
|
||||
return <Text>Install docker and restart the CLI to proceed.</Text>;
|
||||
}
|
||||
};
|
||||
|
||||
export default Docker;
|
||||
@@ -1,132 +0,0 @@
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import { Next } from "../../types";
|
||||
import YesNo from "../util/YesNo";
|
||||
import { installDockerUbuntu, InstallLog } from "../../helpers/docker";
|
||||
|
||||
const InstallDocker = ({ next }: { next: Next }) => {
|
||||
const [stage, setStage] = useState<
|
||||
| "sysCtlEnable"
|
||||
| "confirm"
|
||||
| "install"
|
||||
| "installing"
|
||||
| "finish"
|
||||
| "error"
|
||||
>("sysCtlEnable");
|
||||
const [sysCtlEnable, setSysCtlEnable] = useState<"yes" | "no">();
|
||||
const [logs, setLogs] = useState<InstallLog[]>([]);
|
||||
useInput(async (_, key) => {
|
||||
if (key.return) {
|
||||
switch (stage) {
|
||||
case "confirm":
|
||||
const log = await installDockerUbuntu(
|
||||
(log) => setLogs((logs) => [...logs, log]),
|
||||
sysCtlEnable === "yes"
|
||||
);
|
||||
if (log) {
|
||||
// there was some error
|
||||
setLogs((logs) => [...logs, log])
|
||||
setStage("error");
|
||||
} else {
|
||||
setStage("finish");
|
||||
}
|
||||
break;
|
||||
|
||||
case "finish":
|
||||
next();
|
||||
break;
|
||||
|
||||
case "error":
|
||||
setSysCtlEnable(undefined);
|
||||
setStage("sysCtlEnable");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (key.leftArrow) {
|
||||
switch (stage) {
|
||||
case "confirm":
|
||||
setSysCtlEnable(undefined);
|
||||
setStage("sysCtlEnable");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text color="cyan" bold>
|
||||
Docker Install Helper
|
||||
</Text>
|
||||
<Newline />
|
||||
{stage === "sysCtlEnable" && sysCtlEnable === undefined && (
|
||||
<YesNo
|
||||
label="start docker on system start (boot)?"
|
||||
labelColor="white"
|
||||
onSelect={(res) => {
|
||||
setSysCtlEnable(res);
|
||||
setStage("confirm");
|
||||
}}
|
||||
direction="vertical"
|
||||
/>
|
||||
)}
|
||||
{sysCtlEnable !== undefined && (
|
||||
<Text color="green">
|
||||
start on boot: <Text color="white">{sysCtlEnable}</Text>
|
||||
</Text>
|
||||
)}
|
||||
{stage === "confirm" && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>
|
||||
press <Text color="green">enter</Text> to install docker
|
||||
</Text>
|
||||
</Fragment>
|
||||
)}
|
||||
{(stage === "installing" || stage === "finish") && (
|
||||
<Fragment>
|
||||
{stage === "installing" && <Text color="cyan">installing...</Text>}
|
||||
<Newline />
|
||||
{logs.map(({ stage, log }) => {
|
||||
<Fragment>
|
||||
<Text color="cyan" bold>
|
||||
{stage}
|
||||
</Text>
|
||||
<Text color="green">
|
||||
command: <Text color="white">{log.command}</Text>
|
||||
</Text>
|
||||
{log.log.stdout ? (
|
||||
<Text color="green">
|
||||
stdout: <Text color="white">{log.log.stdout}</Text>
|
||||
</Text>
|
||||
) : undefined}
|
||||
{log.log.stderr ? (
|
||||
<Text color="red">
|
||||
stderr: <Text color="white">{log.log.stderr}</Text>
|
||||
</Text>
|
||||
) : undefined}
|
||||
<Newline />
|
||||
</Fragment>;
|
||||
})}
|
||||
</Fragment>
|
||||
)}
|
||||
{stage === "finish" && (
|
||||
<Text>
|
||||
Docker has finished installing. Press <Text color="green">enter</Text>{" "}
|
||||
to continue.
|
||||
</Text>
|
||||
)}
|
||||
{stage === "error" && (
|
||||
<Text>
|
||||
There was an error during install. Press{" "}
|
||||
<Text color="green">enter</Text> to try again.
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default InstallDocker;
|
||||
@@ -1,105 +0,0 @@
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import React, { useState } from "react";
|
||||
import { useBlinker } from "../../hooks";
|
||||
import { SetConfig } from "../../types";
|
||||
import YesNo from "../util/YesNo";
|
||||
import SetupMongo from "./SetupMongo";
|
||||
|
||||
const Mongo = ({
|
||||
setConfig,
|
||||
next,
|
||||
}: {
|
||||
setConfig: SetConfig;
|
||||
next: () => void;
|
||||
}) => {
|
||||
const [setup, setSetup] = useState<boolean>();
|
||||
const [mongoURL, setMongoUrl] = useState("mongodb://127.0.0.1:27017/monitor");
|
||||
const [confirm, setConfirm] = useState(false);
|
||||
const blinker = useBlinker();
|
||||
|
||||
useInput((input, key) => {
|
||||
if (setup === false) {
|
||||
if (key.return) {
|
||||
if (confirm) {
|
||||
setConfig("mongoURL", mongoURL);
|
||||
next();
|
||||
} else {
|
||||
setConfirm(true);
|
||||
}
|
||||
} else if (!confirm && key.delete) {
|
||||
setMongoUrl(mongoURL.slice(0, mongoURL.length - 1));
|
||||
} else if (key.leftArrow) {
|
||||
setConfirm(false);
|
||||
} else if (!confirm) {
|
||||
setMongoUrl(mongoURL + input);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (setup === undefined) {
|
||||
return (
|
||||
<YesNo
|
||||
label={
|
||||
<Text>
|
||||
Do you need to set up mongo db locally? This will begin the{" "}
|
||||
<Text color="cyan" bold>
|
||||
Mongo Setup Helper
|
||||
</Text>
|
||||
.
|
||||
</Text>
|
||||
}
|
||||
onYes={() => {
|
||||
setSetup(true);
|
||||
}}
|
||||
onNo={() => {
|
||||
setSetup(false);
|
||||
}}
|
||||
labelColor="white"
|
||||
direction="vertical"
|
||||
/>
|
||||
);
|
||||
} else if (setup) {
|
||||
return (
|
||||
<SetupMongo
|
||||
blinker={blinker}
|
||||
onFinished={(mongoURL) => {
|
||||
setConfig("mongoURL", mongoURL);
|
||||
next();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Box flexDirection="row">
|
||||
<Text color="green">mongo url: </Text>
|
||||
<Text>
|
||||
{mongoURL}
|
||||
{blinker && !confirm ? "|" : ""}
|
||||
</Text>
|
||||
</Box>
|
||||
<Newline />
|
||||
<Text color="gray">
|
||||
note: remember to specify the database name in the url, ie
|
||||
mongodb://localhost:27017<Text color="green">/monitor</Text>
|
||||
</Text>
|
||||
<Newline />
|
||||
{confirm && (
|
||||
<Text>
|
||||
press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to confirm mongo url or press the{" "}
|
||||
<Text color="blue" bold>
|
||||
left arrow
|
||||
</Text>{" "}
|
||||
on your keyboard to continue editing.
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Mongo;
|
||||
@@ -1,274 +0,0 @@
|
||||
import { CommandLogError } from "@monitor/types";
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { startMongo } from "../../helpers/deploy/mongo";
|
||||
import LabelledSelector from "../util/LabelledSelector";
|
||||
import YesNo from "../util/YesNo";
|
||||
|
||||
const RESTART_MODES = ["no", "on-failure", "always", "unless-stopped"];
|
||||
|
||||
const SetupMongo = ({
|
||||
onFinished,
|
||||
blinker,
|
||||
}: {
|
||||
onFinished: (mongoURL: string) => void;
|
||||
blinker: boolean;
|
||||
}) => {
|
||||
const [stage, setStage] = useState<
|
||||
"name" | "port" | "volume" | "restart" | "confirm" | "finish"
|
||||
>("name"); // 0: name, 1: port, 2: volume, 3: restart
|
||||
const [name, setName] = useState("mongo-db");
|
||||
const [port, setPort] = useState<string>();
|
||||
const [volume, setVolume] = useState<string | false>();
|
||||
const [restart, setRestart] = useState<string>();
|
||||
const [running, setRunning] = useState(false);
|
||||
const [result, setResult] = useState<CommandLogError>();
|
||||
useInput((input, key) => {
|
||||
if (key.return) {
|
||||
switch (stage) {
|
||||
case "name":
|
||||
setStage("port");
|
||||
setPort("27017");
|
||||
break;
|
||||
|
||||
case "port":
|
||||
if (!isNaN(Number(port))) {
|
||||
setStage("volume");
|
||||
}
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
if (volume) {
|
||||
setStage("restart");
|
||||
}
|
||||
break;
|
||||
|
||||
case "restart":
|
||||
if (restart) {
|
||||
setStage("confirm");
|
||||
}
|
||||
break;
|
||||
|
||||
case "confirm":
|
||||
setRunning(true);
|
||||
startMongo(name, Number(port!), volume!, restart!).then((res) => {
|
||||
setResult(res);
|
||||
setStage("finish");
|
||||
});
|
||||
break;
|
||||
|
||||
case "finish":
|
||||
if (!result?.isError) {
|
||||
onFinished(`mongodb://127.0.0.1:${port}/monitor`);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (key.leftArrow) {
|
||||
switch (stage) {
|
||||
case "port":
|
||||
setPort(undefined);
|
||||
setStage("name");
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
setVolume(undefined);
|
||||
setStage("port");
|
||||
break;
|
||||
|
||||
case "restart":
|
||||
setRestart(undefined);
|
||||
if (volume === false) {
|
||||
setVolume(undefined);
|
||||
}
|
||||
setStage("volume");
|
||||
break;
|
||||
|
||||
case "confirm":
|
||||
setRestart(undefined);
|
||||
setStage("restart");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (key.delete) {
|
||||
switch (stage) {
|
||||
case "name":
|
||||
setName(name.slice(0, Math.max(0, name.length - 1)));
|
||||
break;
|
||||
|
||||
case "port":
|
||||
if (port) setPort(port.slice(0, Math.max(0, port.length - 1)));
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
if (volume)
|
||||
setVolume(volume.slice(0, Math.max(0, volume.length - 1)));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (stage) {
|
||||
case "name":
|
||||
setName(name + input);
|
||||
break;
|
||||
|
||||
case "port":
|
||||
const newPort = Number(port + input);
|
||||
if (!isNaN(newPort)) {
|
||||
setPort(newPort.toString());
|
||||
}
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
if (volume) setVolume(volume + input);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text color="cyan" bold>
|
||||
Mongo Setup Helper
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text>
|
||||
press your keyboard back arrow ({"<-"}) to go back to the previous field
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text color="green">
|
||||
container name:{" "}
|
||||
<Text color="white">
|
||||
{name}
|
||||
{stage === "name" && blinker ? "|" : ""}
|
||||
</Text>
|
||||
</Text>
|
||||
{port && (
|
||||
<Text color="green">
|
||||
port:{" "}
|
||||
<Text color="white">
|
||||
{port}
|
||||
{stage === "port" && blinker ? "|" : ""}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
{stage === "volume" && volume === undefined && (
|
||||
<LabelledSelector
|
||||
label="mount data on local filesystem:"
|
||||
items={["yes", "no"]}
|
||||
onSelect={(use) => {
|
||||
if (use === "yes") {
|
||||
setVolume("~/mongo");
|
||||
} else {
|
||||
setVolume(false);
|
||||
setStage("restart");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{(volume || volume === false) && (
|
||||
<Text color="green">
|
||||
{volume ? "mount folder: " : "mount: "}
|
||||
<Text color="white">
|
||||
{volume || "no"}
|
||||
{stage === "volume" && blinker ? "|" : ""}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
{stage === "restart" && restart === undefined && (
|
||||
<LabelledSelector
|
||||
label="restart:"
|
||||
items={RESTART_MODES}
|
||||
onSelect={(mode) => {
|
||||
setRestart(mode);
|
||||
setStage("confirm");
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{restart !== undefined && (
|
||||
<Text color="green">
|
||||
restart: <Text color="white">{restart}</Text>
|
||||
</Text>
|
||||
)}
|
||||
{/* {stage === "confirm" && (
|
||||
<Box flexDirection="column">
|
||||
<Newline />
|
||||
{running ? (
|
||||
<Text color="cyan">running...</Text>
|
||||
) : (
|
||||
<Text color="green">press enter to start mongo...</Text>
|
||||
)}
|
||||
</Box>
|
||||
)} */}
|
||||
{stage === "confirm" && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
{running ? (
|
||||
<Text color="cyan">running...</Text>
|
||||
) : (
|
||||
<Text>
|
||||
press <Text color="green">enter</Text> to start mongo...
|
||||
</Text>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{result && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>command: {result.command}</Text>
|
||||
{result.log.stdout ? (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>stdout: {result.log.stdout}</Text>
|
||||
</Fragment>
|
||||
) : undefined}
|
||||
{result.log.stderr ? (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>stderr: {result.log.stderr}</Text>
|
||||
</Fragment>
|
||||
) : undefined}
|
||||
</Fragment>
|
||||
)}
|
||||
{stage === "finish" && result && !result.isError && (
|
||||
<Text>
|
||||
Success! Press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to continue
|
||||
</Text>
|
||||
)}
|
||||
{stage === "finish" && result && result.isError && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<YesNo
|
||||
label="looks like that failed, would you like to retry?"
|
||||
labelColor="white"
|
||||
onYes={() => {
|
||||
setPort(undefined);
|
||||
setVolume(undefined);
|
||||
setRestart(undefined);
|
||||
setResult(undefined);
|
||||
setStage("name");
|
||||
}}
|
||||
onNo={() => {
|
||||
onFinished(`mongodb://127.0.0.1:${port}/monitor`);
|
||||
}}
|
||||
direction="vertical"
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SetupMongo;
|
||||
@@ -1,100 +0,0 @@
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import React, { useState } from "react";
|
||||
import { useBlinker } from "../../hooks";
|
||||
import { SetConfig } from "../../types";
|
||||
import YesNo from "../util/YesNo";
|
||||
import SetupRegistry from "./SetupRegistry";
|
||||
|
||||
const Registry = ({
|
||||
setConfig,
|
||||
next,
|
||||
}: {
|
||||
setConfig: SetConfig;
|
||||
next: () => void;
|
||||
}) => {
|
||||
const [setup, setSetup] = useState<boolean>();
|
||||
const [registryURL, setRegistryURL] = useState("http://127.0.0.1:5000/");
|
||||
const [confirm, setConfirm] = useState(false);
|
||||
const blinker = useBlinker();
|
||||
|
||||
useInput((input, key) => {
|
||||
if (setup === false) {
|
||||
if (key.return) {
|
||||
if (confirm) {
|
||||
setConfig("registryURL", registryURL);
|
||||
next();
|
||||
} else {
|
||||
setConfirm(true);
|
||||
}
|
||||
} else if (!confirm && key.delete) {
|
||||
setRegistryURL(registryURL.slice(0, registryURL.length - 1));
|
||||
} else if (key.leftArrow) {
|
||||
setConfirm(false);
|
||||
} else if (!confirm) {
|
||||
setRegistryURL(registryURL + input);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (setup === undefined) {
|
||||
return (
|
||||
<YesNo
|
||||
label={
|
||||
<Text>
|
||||
Do you need to set up a docker registry locally? This will begin the{" "}
|
||||
<Text color="cyan" bold>
|
||||
Registry Setup Helper
|
||||
</Text>
|
||||
.
|
||||
</Text>
|
||||
}
|
||||
onYes={() => {
|
||||
setSetup(true);
|
||||
}}
|
||||
onNo={() => {
|
||||
setSetup(false);
|
||||
}}
|
||||
labelColor="white"
|
||||
direction="vertical"
|
||||
/>
|
||||
);
|
||||
} else if (setup) {
|
||||
return (
|
||||
<SetupRegistry
|
||||
blinker={blinker}
|
||||
onFinished={(registryURL) => {
|
||||
setConfig("registryURL", registryURL);
|
||||
next();
|
||||
}}
|
||||
/>
|
||||
);
|
||||
} else {
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Box flexDirection="row">
|
||||
<Text color="green">registry url: </Text>
|
||||
<Text>
|
||||
{registryURL}
|
||||
{blinker && !confirm ? "|" : ""}
|
||||
</Text>
|
||||
</Box>
|
||||
<Newline />
|
||||
{confirm && (
|
||||
<Text>
|
||||
press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to confirm registry url or press the{" "}
|
||||
<Text color="blue" bold>
|
||||
left arrow
|
||||
</Text>{" "}
|
||||
on your keyboard to continue editing.
|
||||
</Text>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
export default Registry;
|
||||
@@ -1,274 +0,0 @@
|
||||
import { CommandLogError } from "@monitor/types";
|
||||
import { Box, Newline, Text, useInput } from "ink";
|
||||
import React, { Fragment, useState } from "react";
|
||||
import { startRegistry } from "../../helpers/deploy/registry";
|
||||
import LabelledSelector from "../util/LabelledSelector";
|
||||
import YesNo from "../util/YesNo";
|
||||
|
||||
const RESTART_MODES = ["no", "on-failure", "always", "unless-stopped"];
|
||||
|
||||
const SetupRegistry = ({
|
||||
onFinished,
|
||||
blinker,
|
||||
}: {
|
||||
onFinished: (registryURL: string) => void;
|
||||
blinker: boolean;
|
||||
}) => {
|
||||
const [stage, setStage] = useState<
|
||||
"name" | "port" | "volume" | "restart" | "confirm" | "finish"
|
||||
>("name"); // 0: name, 1: port, 2: volume, 3: restart
|
||||
const [name, setName] = useState("monitor-registry");
|
||||
const [port, setPort] = useState<string>();
|
||||
const [volume, setVolume] = useState<string | false>();
|
||||
const [restart, setRestart] = useState<string>();
|
||||
const [running, setRunning] = useState(false);
|
||||
const [result, setResult] = useState<CommandLogError>();
|
||||
useInput((input, key) => {
|
||||
if (key.return) {
|
||||
switch (stage) {
|
||||
case "name":
|
||||
setStage("port");
|
||||
setPort("5000");
|
||||
break;
|
||||
|
||||
case "port":
|
||||
if (!isNaN(Number(port))) {
|
||||
setStage("volume");
|
||||
}
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
if (volume) {
|
||||
setStage("restart");
|
||||
}
|
||||
break;
|
||||
|
||||
case "restart":
|
||||
if (restart) {
|
||||
setStage("confirm");
|
||||
}
|
||||
break;
|
||||
|
||||
case "confirm":
|
||||
setRunning(true);
|
||||
startRegistry(name, Number(port!), volume!, restart!).then((res) => {
|
||||
setResult(res);
|
||||
setStage("finish");
|
||||
});
|
||||
break;
|
||||
|
||||
case "finish":
|
||||
if (!result?.isError) {
|
||||
onFinished(`http://127.0.0.1:${port}/`);
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (key.leftArrow) {
|
||||
switch (stage) {
|
||||
case "port":
|
||||
setPort(undefined);
|
||||
setStage("name");
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
setVolume(undefined);
|
||||
setStage("port");
|
||||
break;
|
||||
|
||||
case "restart":
|
||||
setRestart(undefined);
|
||||
if (volume === false) {
|
||||
setVolume(undefined);
|
||||
}
|
||||
setStage("volume");
|
||||
break;
|
||||
|
||||
case "confirm":
|
||||
setRestart(undefined);
|
||||
setStage("restart");
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (key.delete) {
|
||||
switch (stage) {
|
||||
case "name":
|
||||
setName(name.slice(0, Math.max(0, name.length - 1)));
|
||||
break;
|
||||
|
||||
case "port":
|
||||
if (port) setPort(port.slice(0, Math.max(0, port.length - 1)));
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
if (volume)
|
||||
setVolume(volume.slice(0, Math.max(0, volume.length - 1)));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
switch (stage) {
|
||||
case "name":
|
||||
setName(name + input);
|
||||
break;
|
||||
|
||||
case "port":
|
||||
const newPort = Number(port + input);
|
||||
if (!isNaN(newPort)) {
|
||||
setPort(newPort.toString());
|
||||
}
|
||||
break;
|
||||
|
||||
case "volume":
|
||||
if (volume) setVolume(volume + input);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
return (
|
||||
<Box flexDirection="column">
|
||||
<Text color="cyan" bold>
|
||||
Registry Setup Helper
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text>
|
||||
press your keyboard back arrow ({"<-"}) to go back to the previous field
|
||||
</Text>
|
||||
<Newline />
|
||||
<Text color="green">
|
||||
container name:{" "}
|
||||
<Text color="white">
|
||||
{name}
|
||||
{stage === "name" && blinker ? "|" : ""}
|
||||
</Text>
|
||||
</Text>
|
||||
{port && (
|
||||
<Text color="green">
|
||||
port:{" "}
|
||||
<Text color="white">
|
||||
{port}
|
||||
{stage === "port" && blinker ? "|" : ""}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
{stage === "volume" && volume === undefined && (
|
||||
<LabelledSelector
|
||||
label="mount data on local filesystem:"
|
||||
items={["yes", "no"]}
|
||||
onSelect={(use) => {
|
||||
if (use === "yes") {
|
||||
setVolume("~/registry");
|
||||
} else {
|
||||
setVolume(false);
|
||||
setStage("restart");
|
||||
}
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{(volume || volume === false) && (
|
||||
<Text color="green">
|
||||
{volume ? "mount folder: " : "mount: "}
|
||||
<Text color="white">
|
||||
{volume || "no"}
|
||||
{stage === "volume" && blinker ? "|" : ""}
|
||||
</Text>
|
||||
</Text>
|
||||
)}
|
||||
{stage === "restart" && restart === undefined && (
|
||||
<LabelledSelector
|
||||
label="restart:"
|
||||
items={RESTART_MODES}
|
||||
onSelect={(mode) => {
|
||||
setRestart(mode);
|
||||
setStage("confirm");
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
{restart !== undefined && (
|
||||
<Text color="green">
|
||||
restart: <Text color="white">{restart}</Text>
|
||||
</Text>
|
||||
)}
|
||||
{/* {stage === "confirm" && (
|
||||
<Box flexDirection="column">
|
||||
<Newline />
|
||||
{running ? (
|
||||
<Text color="cyan">running...</Text>
|
||||
) : (
|
||||
<Text color="green">press enter to start mongo...</Text>
|
||||
)}
|
||||
</Box>
|
||||
)} */}
|
||||
{stage === "confirm" && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
{running ? (
|
||||
<Text color="cyan">running...</Text>
|
||||
) : (
|
||||
<Text>
|
||||
press <Text color="green">enter</Text> to start the registry...
|
||||
</Text>
|
||||
)}
|
||||
</Fragment>
|
||||
)}
|
||||
{result && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>command: {result.command}</Text>
|
||||
{result.log.stdout ? (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>stdout: {result.log.stdout}</Text>
|
||||
</Fragment>
|
||||
) : undefined}
|
||||
{result.log.stderr ? (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<Text>stderr: {result.log.stderr}</Text>
|
||||
</Fragment>
|
||||
) : undefined}
|
||||
</Fragment>
|
||||
)}
|
||||
{stage === "finish" && result && !result.isError && (
|
||||
<Text>
|
||||
Success! Press{" "}
|
||||
<Text color="green" bold>
|
||||
enter
|
||||
</Text>{" "}
|
||||
to continue
|
||||
</Text>
|
||||
)}
|
||||
{stage === "finish" && result && result.isError && (
|
||||
<Fragment>
|
||||
<Newline />
|
||||
<YesNo
|
||||
label="looks like that failed, would you like to retry?"
|
||||
labelColor="white"
|
||||
onYes={() => {
|
||||
setPort(undefined);
|
||||
setVolume(undefined);
|
||||
setRestart(undefined);
|
||||
setResult(undefined);
|
||||
setStage("name");
|
||||
}}
|
||||
onNo={() => {
|
||||
onFinished(`http://127.0.0.1:${port}/`);
|
||||
}}
|
||||
direction="vertical"
|
||||
/>
|
||||
</Fragment>
|
||||
)}
|
||||
</Box>
|
||||
);
|
||||
};
|
||||
|
||||
export default SetupRegistry;
|
||||
@@ -1,2 +0,0 @@
|
||||
export const CORE_IMAGE = "mbecker2020/monitor-core";
|
||||
export const PERIPHERY_IMAGE = "mbecker2020/monitor-periphery";
|
||||
@@ -1,13 +0,0 @@
|
||||
import { execute } from "../execute";
|
||||
|
||||
export async function startMongo(
|
||||
name: string,
|
||||
port: number,
|
||||
volume: string | false,
|
||||
restart: string
|
||||
) {
|
||||
const command = `docker run -d --name ${name} -p ${port}:27017${
|
||||
volume ? ` -v ${volume}:/data/db` : ""
|
||||
} --restart ${restart} mongo:latest`;
|
||||
return await execute(command);
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
import { CORE_IMAGE } from "../../config";
|
||||
import { Config } from "../../types";
|
||||
import { execute } from "../execute";
|
||||
|
||||
export async function startMonitorCore({
|
||||
monitorCore: {
|
||||
|
||||
},
|
||||
mongo: { url: mongoURL },
|
||||
registry: { url: registryURL },
|
||||
}: Config) {
|
||||
const command = `docker run -d --name monitor-core -e MONGO_URL=${mongoURL}${
|
||||
registryURL ? ` -e REGISTRY_URL=${registryURL}` : ""
|
||||
} ${CORE_IMAGE}`;
|
||||
return await execute(command);
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { execute } from "../execute";
|
||||
|
||||
export async function startRegistry(
|
||||
name: string,
|
||||
port: number,
|
||||
volume: string | false,
|
||||
restart: string
|
||||
) {
|
||||
const command = `docker run -d --name ${name} -p ${port}:5000${
|
||||
volume ? ` -v ${volume}:/var/lib/registry` : ""
|
||||
} --restart ${restart} registry:2`;
|
||||
return await execute(command);
|
||||
}
|
||||
+35
-32
@@ -12,15 +12,15 @@ export async function installDockerUbuntu(
|
||||
) {
|
||||
const total = 6 + (systemCtlEnable ? 1 : 0);
|
||||
const update = await execute("sudo apt-get update");
|
||||
if (update.isError) return {
|
||||
stage: "error updating system",
|
||||
log: update
|
||||
};
|
||||
onCommandEnd({
|
||||
if (update.isError)
|
||||
return {
|
||||
stage: "error updating system",
|
||||
log: update,
|
||||
};
|
||||
onCommandEnd({
|
||||
stage: `updated system (1 of ${total})`,
|
||||
log: update,
|
||||
});
|
||||
|
||||
|
||||
const installDeps = await execute(`
|
||||
sudo apt-get install \
|
||||
@@ -29,38 +29,39 @@ export async function installDockerUbuntu(
|
||||
gnupg \
|
||||
lsb-release
|
||||
`);
|
||||
if (installDeps.isError) return {
|
||||
stage: "error installing dependencies",
|
||||
log: installDeps
|
||||
};
|
||||
onCommandEnd({
|
||||
if (installDeps.isError)
|
||||
return {
|
||||
stage: "error installing dependencies",
|
||||
log: installDeps,
|
||||
};
|
||||
onCommandEnd({
|
||||
stage: `installed dependencies (2 of ${total})`,
|
||||
log: installDeps,
|
||||
});
|
||||
|
||||
|
||||
const addKey = await execute(
|
||||
"curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg"
|
||||
);
|
||||
if (addKey.isError) return {
|
||||
stage: "error adding docker key",
|
||||
log: addKey,
|
||||
};
|
||||
onCommandEnd({
|
||||
if (addKey.isError)
|
||||
return {
|
||||
stage: "error adding docker key",
|
||||
log: addKey,
|
||||
};
|
||||
onCommandEnd({
|
||||
stage: `added docker key (3 of ${total})`,
|
||||
log: addKey,
|
||||
});
|
||||
|
||||
|
||||
const setStableRepository = await execute(`
|
||||
echo \
|
||||
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
|
||||
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
|
||||
`);
|
||||
if (setStableRepository.isError) return {
|
||||
stage: "error adding stable repository",
|
||||
log: setStableRepository,
|
||||
};
|
||||
if (setStableRepository.isError)
|
||||
return {
|
||||
stage: "error adding stable repository",
|
||||
log: setStableRepository,
|
||||
};
|
||||
onCommandEnd({
|
||||
stage: `set docker stable repository (4 of ${total})`,
|
||||
log: setStableRepository,
|
||||
@@ -69,10 +70,11 @@ export async function installDockerUbuntu(
|
||||
const installDocker = await execute(
|
||||
"sudo apt-get udpate && sudo apt-get install docker-ce docker-ce-cli containerd.io"
|
||||
);
|
||||
if (installDocker.isError) return {
|
||||
stage: "error installing docker",
|
||||
log: installDocker,
|
||||
};
|
||||
if (installDocker.isError)
|
||||
return {
|
||||
stage: "error installing docker",
|
||||
log: installDocker,
|
||||
};
|
||||
onCommandEnd({
|
||||
stage: `installed docker (5 of ${total})`,
|
||||
log: installDocker,
|
||||
@@ -95,10 +97,11 @@ export async function installDockerUbuntu(
|
||||
const startOnBoot = await execute(
|
||||
"sudo systemctl enable docker.service && sudo systemctl enable containerd.service"
|
||||
);
|
||||
if (startOnBoot.isError) return {
|
||||
stage: "error configuring to start on boot",
|
||||
log: startOnBoot,
|
||||
};
|
||||
if (startOnBoot.isError)
|
||||
return {
|
||||
stage: "error configuring to start on boot",
|
||||
log: startOnBoot,
|
||||
};
|
||||
onCommandEnd({
|
||||
stage: `configured to start on boot (7 of ${total})`,
|
||||
log: startOnBoot,
|
||||
@@ -109,6 +112,6 @@ export async function installDockerUbuntu(
|
||||
}
|
||||
|
||||
export async function checkDockerNotInstalled() {
|
||||
const res = await execute("docker ps");
|
||||
return res.isError
|
||||
const res = await execute("docker ps");
|
||||
return res.isError;
|
||||
}
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
export function toDashedName(name: string) {
|
||||
return name.toLowerCase().replaceAll(" ", "-");
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
import { Deployment } from "@monitor/types";
|
||||
import { model, Schema } from "mongoose";
|
||||
|
||||
export default function deploymentModel() {
|
||||
const Conversion = new Schema({
|
||||
local: String,
|
||||
container: String,
|
||||
});
|
||||
|
||||
const Volume = new Schema({
|
||||
variable: String,
|
||||
value: String,
|
||||
});
|
||||
|
||||
const EnvironmentVar = new Schema({
|
||||
variable: String,
|
||||
value: String,
|
||||
});
|
||||
|
||||
const schema = new Schema<Deployment>({
|
||||
name: { type: String, unique: true, index: true },
|
||||
containerName: { type: String, unique: true, index: true }, // for auto pull of frontend repo as well
|
||||
owner: { type: String, index: true },
|
||||
serverID: { type: String, index: true },
|
||||
buildID: { type: String, index: true }, // if deploying a monitor build
|
||||
/* to create docker run command */
|
||||
image: String, // used if deploying an external image (from docker hub)
|
||||
latest: Boolean, // if custom image, use this to add :latest
|
||||
ports: [Conversion],
|
||||
volumes: [Volume],
|
||||
environment: [EnvironmentVar],
|
||||
network: String,
|
||||
restart: String,
|
||||
postImage: String, // interpolated into run command after the image String
|
||||
containerUser: String, // after -u in the run command
|
||||
/* to manage repo for static frontend, mounted as a volume */
|
||||
repo: String,
|
||||
branch: { type: String, default: "master" },
|
||||
accessToken: String,
|
||||
containerMount: String, // the file path to mount repo on inside the container
|
||||
});
|
||||
|
||||
return model("Deployment", schema)
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import { Deployment } from "@monitor/types";
|
||||
import mongoose from "mongoose";
|
||||
import deploymentModel from "./deployment";
|
||||
import serverModel from "./server";
|
||||
import userModel from "./user";
|
||||
|
||||
export async function addInitialDocs(mongoURL: string, localMongo: boolean, localRegistry: boolean) {
|
||||
await mongoose.connect(mongoURL);
|
||||
|
||||
const servers = serverModel();
|
||||
const deployments = deploymentModel();
|
||||
const users = userModel();
|
||||
|
||||
const coreServer = {
|
||||
name: "Core Server",
|
||||
address: "localhost",
|
||||
passkey: "passkey",
|
||||
enabled: true,
|
||||
isCore: true,
|
||||
};
|
||||
const coreServerID = (await servers.create(coreServer)).toObject()._id;
|
||||
|
||||
const coreDeployment: Deployment = {
|
||||
name: "Monitor Core",
|
||||
containerName: "monitor-core",
|
||||
image: "mbecker2020/monitor-core",
|
||||
latest: true,
|
||||
serverID: coreServerID,
|
||||
owner: "admin",
|
||||
};
|
||||
deployments.create(coreDeployment);
|
||||
|
||||
if (localMongo) {
|
||||
const mongoDeployment: Deployment = {
|
||||
name: "Mongo DB",
|
||||
containerName: "mongo-db",
|
||||
image: "mongo",
|
||||
latest: true,
|
||||
owner: "admin",
|
||||
};
|
||||
deployments.create(mongoDeployment);
|
||||
}
|
||||
|
||||
if (localRegistry) {
|
||||
const registryDeployment: Deployment = {
|
||||
name: "Registry",
|
||||
containerName: "registry",
|
||||
image: "registry:2",
|
||||
serverID: coreServerID,
|
||||
owner: "admin",
|
||||
};
|
||||
deployments.create(registryDeployment);
|
||||
}
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { Server } from "@monitor/types";
|
||||
import { model, Schema } from "mongoose";
|
||||
|
||||
export default function serverModel() {
|
||||
const schema = new Schema<Server>({
|
||||
name: { type: String, unique: true },
|
||||
address: String,
|
||||
passkey: String,
|
||||
enabled: { type: Boolean, default: true },
|
||||
isCore: Boolean,
|
||||
});
|
||||
|
||||
return model("Server", schema);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { User } from "@monitor/types";
|
||||
import { Schema, model } from "mongoose";
|
||||
|
||||
export default function userModel() {
|
||||
const schema = new Schema<User>({
|
||||
username: { type: String, index: true, required: true },
|
||||
permissions: { type: Number, default: 0 },
|
||||
password: String,
|
||||
avatar: String,
|
||||
githubID: { type: Number, index: true },
|
||||
});
|
||||
|
||||
return model("User", schema);
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import { useCallback, useEffect, useState } from "react";
|
||||
|
||||
export function useSequence(): [
|
||||
current: number,
|
||||
next: () => void,
|
||||
prev: () => void
|
||||
] {
|
||||
const [current, setCurrent] = useState(0);
|
||||
const next = useCallback(() => {
|
||||
setCurrent((current) => current + 1);
|
||||
}, []);
|
||||
const prev = useCallback(() => {
|
||||
setCurrent((current) => Math.max(current - 1, 0));
|
||||
}, []);
|
||||
return [current, next, prev];
|
||||
}
|
||||
|
||||
export function useConfig<T>(
|
||||
init: T
|
||||
): [T, (field: keyof T, val: number | string | boolean) => void] {
|
||||
const [config, setConfig] = useState(init);
|
||||
const set = useCallback((field: keyof T, val: string | number | boolean) => {
|
||||
setConfig((config) => ({ ...config, [field]: val }));
|
||||
}, []);
|
||||
return [config, set];
|
||||
}
|
||||
|
||||
export function useBlinker(interval = 750) {
|
||||
const [on, setOn] = useState(false);
|
||||
useEffect(() => {
|
||||
const int = setInterval(() => {
|
||||
setOn(on => !on);
|
||||
}, interval)
|
||||
return () => clearInterval(int);
|
||||
}, []);
|
||||
return on;
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
import React from "react";
|
||||
import { render } from "ink";
|
||||
// import meow from "meow";
|
||||
import App from "./App";
|
||||
import { checkDockerNotInstalled } from "./helpers/docker";
|
||||
|
||||
// const cli = meow(
|
||||
// `
|
||||
// Usage
|
||||
// $ monitor-cli
|
||||
|
||||
// Options
|
||||
// --name Your name
|
||||
|
||||
// Examples
|
||||
// $ cli --name=Jane
|
||||
// Hello, Jane
|
||||
// `,
|
||||
// {
|
||||
// flags: {
|
||||
// name: {
|
||||
// type: "string",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
// );
|
||||
export let dockerNotInstalled = true;
|
||||
checkDockerNotInstalled().then((res) => {
|
||||
dockerNotInstalled = res;
|
||||
render(<App />);
|
||||
});
|
||||
Vendored
+25
-13
@@ -1,29 +1,41 @@
|
||||
export type Config = {
|
||||
monitorCore: {
|
||||
name: string;
|
||||
|
||||
};
|
||||
mongo: {
|
||||
monitorCore?: {
|
||||
name: string;
|
||||
secretVolume: string; // to mount secrets.json into the container
|
||||
hostNetwork?: boolean;
|
||||
port?: number;
|
||||
};
|
||||
monitorPeriphery?: {
|
||||
name: string;
|
||||
hostNetwork?: boolean;
|
||||
port?: number;
|
||||
};
|
||||
mongo?: {
|
||||
url: string;
|
||||
deploymentConfig?: {
|
||||
// if mongo container already exists locally running on docker and should be added as a monitor managed deployment
|
||||
};
|
||||
startConfig?: {
|
||||
// if this is attached, the cli will start container with this config and add
|
||||
};
|
||||
startConfig?: StartConfig;
|
||||
};
|
||||
registry: {
|
||||
registry?: {
|
||||
exists: boolean; // if this is false, dont use a registry and builds will be disabled
|
||||
url?: string;
|
||||
deploymentConfig?: {};
|
||||
startConfig?: {};
|
||||
startConfig?: StartConfig;
|
||||
};
|
||||
};
|
||||
|
||||
export type StartConfig = {
|
||||
// if this is attached, the cli will start container with this config and add
|
||||
name: string;
|
||||
port: number;
|
||||
volume: string | false;
|
||||
restart: string;
|
||||
};
|
||||
|
||||
export type SetConfig = (
|
||||
domain: keyof Config,
|
||||
field: keyof Config[keyof Config],
|
||||
val: string | number | boolean
|
||||
field: keyof Config,
|
||||
val: string | number | boolean
|
||||
) => void;
|
||||
|
||||
export type Next = () => void;
|
||||
|
||||
Reference in New Issue
Block a user