mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-12 23:04:52 +09:00
7 files changed
+84
-8
No files matched your search
@@ -19,6 +19,7 @@
|
||||
- Packaged and uploaded to npm again, greatly simplifying distribution and installation of both Clusterio and plugins.
|
||||
- Added centralized logging for the cluster.
|
||||
All logs from both Clusterio and Factorio is stored in a shared log which can be inspected and queried.
|
||||
- Added remote save management with the ability to list, create, upload, download, delete and load saves for instances.
|
||||
|
||||
### Features
|
||||
|
||||
|
||||
+3
-2
@@ -137,10 +137,11 @@ slaveCommands.add(new libCommand.Command({
|
||||
|
||||
slaveCommands.add(new libCommand.Command({
|
||||
definition: ["generate-token", "Generate token for a slave", (yargs) => {
|
||||
yargs.option("id", { type: "number", nargs: 1, describe: "Slave id", demandOption: true });
|
||||
yargs.option("id", { type: "number", nargs: 1, describe: "Slave id" });
|
||||
}],
|
||||
handler: async function(args, control) {
|
||||
let response = await libLink.messages.generateSlaveToken.send(control, { slave_id: args.id });
|
||||
let slaveId = typeof args.id === "number" ? args.id : null;
|
||||
let response = await libLink.messages.generateSlaveToken.send(control, { slave_id: slaveId });
|
||||
print(response.token);
|
||||
},
|
||||
}));
|
||||
|
||||
@@ -422,7 +422,7 @@ messages.generateSlaveToken = new Request({
|
||||
links: ["control-master"],
|
||||
permission: "core.slave.generate_token",
|
||||
requestProperties: {
|
||||
"slave_id": { type: "integer" },
|
||||
"slave_id": { type: ["integer", "null"] },
|
||||
},
|
||||
responseProperties: {
|
||||
"token": { type: "string" },
|
||||
|
||||
@@ -130,7 +130,11 @@ class ControlConnection extends BaseConnection {
|
||||
}
|
||||
|
||||
async generateSlaveTokenRequestHandler(message) {
|
||||
return { token: this.generateSlaveToken(message.data.slave_id) };
|
||||
let slaveId = message.data.slave_id;
|
||||
if (slaveId === null) {
|
||||
slaveId = Math.random() * 2**31 | 0;
|
||||
}
|
||||
return { token: this.generateSlaveToken(slaveId) };
|
||||
}
|
||||
|
||||
async createSlaveConfigRequestHandler(message) {
|
||||
|
||||
@@ -21,7 +21,8 @@ function CreateInstanceButton(props) {
|
||||
async function createInstance() {
|
||||
let values = form.getFieldsValue();
|
||||
if (!values.instanceName) {
|
||||
form.setFields([{ name: "mapGenSettings", errors: ["Name is required"] }]);
|
||||
form.setFields([{ name: "instanceName", errors: ["Name is required"] }]);
|
||||
return;
|
||||
}
|
||||
|
||||
let instanceConfig = new libConfig.InstanceConfig("control");
|
||||
|
||||
@@ -1,11 +1,73 @@
|
||||
import React, { useContext } from "react";
|
||||
import { Table } from "antd";
|
||||
import React, { useContext, useRef, useState } from "react";
|
||||
import { Button, Form, Input, Modal, PageHeader, Table } from "antd";
|
||||
|
||||
import libLink from "@clusterio/lib/link";
|
||||
|
||||
import ControlContext from "./ControlContext";
|
||||
import PageLayout from "./PageLayout";
|
||||
import { useSlaveList } from "../model/slave";
|
||||
import { notifyErrorHandler } from "../util/notify";
|
||||
|
||||
|
||||
function GenerateSlaveTokenButton(props) {
|
||||
let control = useContext(ControlContext);
|
||||
let [visible, setVisible] = useState(false);
|
||||
let [token, setToken] = useState(null);
|
||||
let [form] = Form.useForm();
|
||||
let tokenTextAreaRef = useRef(null);
|
||||
|
||||
async function generateToken() {
|
||||
let values = form.getFieldsValue();
|
||||
let slaveId = null;
|
||||
if (values.slaveId) {
|
||||
slaveId = Number.parseInt(values.slaveId, 10);
|
||||
if (Number.isNaN(slaveId)) {
|
||||
form.setFields([{ name: "slaveId", errors: ["Must be an integer"] }]);
|
||||
return;
|
||||
}
|
||||
form.setFields([{ name: "slaveId", errors: [] }]);
|
||||
}
|
||||
|
||||
let result = await libLink.messages.generateSlaveToken.send(control, { slave_id: slaveId });
|
||||
setToken(result.token);
|
||||
}
|
||||
|
||||
return <>
|
||||
<Button
|
||||
onClick={() => { setVisible(true); }}
|
||||
>Generate Token</Button>
|
||||
<Modal
|
||||
title="Generate Slave Token"
|
||||
visible={visible}
|
||||
footer={null}
|
||||
onCancel={() => {
|
||||
setVisible(false);
|
||||
setToken(null);
|
||||
form.resetFields();
|
||||
}}
|
||||
>
|
||||
<Form form={form} layout="vertical" requiredMark="optional">
|
||||
<Form.Item name="slaveId" label="Slave ID">
|
||||
<Input/>
|
||||
</Form.Item>
|
||||
<Form.Item>
|
||||
<Button
|
||||
onClick={() => { generateToken().catch(notifyErrorHandler("Error generating token")); }}
|
||||
>Generate</Button>
|
||||
</Form.Item>
|
||||
<Form.Item label="Token" required>
|
||||
<Input.TextArea value={token} autoSize ref={tokenTextAreaRef} />
|
||||
</Form.Item>
|
||||
<Button disabled={token === null} onClick={() => {
|
||||
let textArea = tokenTextAreaRef.current.resizableTextArea.textArea;
|
||||
textArea.select();
|
||||
document.execCommand("copy");
|
||||
window.getSelection().removeAllRanges();
|
||||
}}>Copy</Button>
|
||||
</Form>
|
||||
</Modal>
|
||||
</>;
|
||||
}
|
||||
|
||||
|
||||
export default function SlavesPage() {
|
||||
@@ -13,7 +75,11 @@ export default function SlavesPage() {
|
||||
let [slaveList] = useSlaveList();
|
||||
|
||||
return <PageLayout nav={[{ name: "Slaves" }]}>
|
||||
<h2>Slaves</h2>
|
||||
<PageHeader
|
||||
className="site-page-header"
|
||||
title="Slaves"
|
||||
extra=<GenerateSlaveTokenButton />
|
||||
/>
|
||||
<Table
|
||||
columns={[
|
||||
{
|
||||
|
||||
@@ -167,6 +167,9 @@ describe("Integration of Clusterio", function() {
|
||||
it("runs", async function() {
|
||||
await execCtl("slave generate-token --id 42");
|
||||
});
|
||||
it("runs without an id", async function() {
|
||||
await execCtl("slave generate-token");
|
||||
});
|
||||
});
|
||||
describe("instance list", function() {
|
||||
it("runs", async function() {
|
||||
|
||||
Reference in new issue
Block a user