Flatten lib namespace

Move all functions and classes currently available through lib/name and
libName to be under a single flat namespace in lib.  This make
reorganising the lib namespace much simpler as the location of symbols
can move without breaking the consumers of lib.

The multi-entrypoint design was already problematic for the web plugin
system which couldn't effectively use it due to how webpack's shared
module system is awkward to set up with multiple entrypoints per package.
This commit is contained in:
Hornwitser committed 2023-07-28 16:03:29 +02:00
1 parent bb58670597
commit bfe119eaa3
143 files changed
+1798 -1918

No files matched your search

+10 -13
View File
@@ -1,19 +1,16 @@
"use strict";
const libData = require("@clusterio/lib/data");
const libErrors = require("@clusterio/lib/errors");
const libLink = require("@clusterio/lib/link");
const { logger } = require("@clusterio/lib/logging");
const libPlugin = require("@clusterio/lib/plugin");
const lib = require("@clusterio/lib");
const { logger } = lib;
const ControllerRouter = require("./ControllerRouter");
/**
* Base class for controller connections
*
* @extends module:lib/link.Link
* @extends module:lib.Link
* @alias module:controller/src/BaseConnection
*/
class BaseConnection extends libLink.Link {
class BaseConnection extends lib.Link {
constructor(connector, controller) {
/** @member {module:controller/src/WsServerConnector} module:controller/src/BaseConnection#connector */
super(connector);
@@ -24,15 +21,15 @@ class BaseConnection extends libLink.Link {
for (let [Event, handler] of controller._registeredEvents) { this.handle(Event, handler); }
for (let [Event, handler] of controller._snoopedEvents) { this.snoopEvent(Event, handler); }
this.handle(libData.ModPackGetRequest, this.handleModPackGetRequest.bind(this));
this.handle(libData.ModPackGetDefaultRequest, this.handleModPackGetDefaultRequest.bind(this));
this.handle(lib.ModPackGetRequest, this.handleModPackGetRequest.bind(this));
this.handle(lib.ModPackGetDefaultRequest, this.handleModPackGetDefaultRequest.bind(this));
}
async disconnect(code, reason) {
try {
await this.connector.disconnect();
} catch (err) {
if (!(err instanceof libErrors.SessionLost)) {
if (!(err instanceof lib.SessionLost)) {
logger.error(`"Unexpected error preparing disconnect:\n${err.stack}`);
}
}
@@ -51,7 +48,7 @@ class BaseConnection extends libLink.Link {
let { id } = request;
let modPack = this._controller.modPacks.get(id);
if (!modPack) {
throw new libErrors.RequestError(`Mod pack with ID ${id} does not exist`);
throw new lib.RequestError(`Mod pack with ID ${id} does not exist`);
}
return modPack;
}
@@ -59,11 +56,11 @@ class BaseConnection extends libLink.Link {
async handleModPackGetDefaultRequest() {
let id = this._controller.config.get("controller.default_mod_pack_id");
if (id === null) {
throw new libErrors.RequestError("Default mod pack not set on controller");
throw new lib.RequestError("Default mod pack not set on controller");
}
let modPack = this._controller.modPacks.get(id);
if (!modPack) {
throw new libErrors.RequestError(`Default mod pack configured (${id}) does not exist`);
throw new lib.RequestError(`Default mod pack configured (${id}) does not exist`);
}
return modPack;
}
+121 -128
View File
@@ -3,22 +3,15 @@ const events = require("events");
const fs = require("fs-extra");
const path = require("path");
const libConfig = require("@clusterio/lib/config");
const libData = require("@clusterio/lib/data");
const libErrors = require("@clusterio/lib/errors");
const libHelpers = require("@clusterio/lib/helpers");
const libLink = require("@clusterio/lib/link");
const { logFilter, logger } = require("@clusterio/lib/logging");
const libLoggingUtils = require("@clusterio/lib/logging_utils");
const libPrometheus = require("@clusterio/lib/prometheus");
const libUsers = require("@clusterio/lib/users");
const lib = require("@clusterio/lib");
const { logFilter, logger } = lib;
const BaseConnection = require("./BaseConnection");
const routes = require("./routes");
const strcmp = new Intl.Collator(undefined, { numerice: "true", sensitivity: "base" }).compare;
const queryLogTime = new libPrometheus.Summary(
const queryLogTime = new lib.Summary(
"clusterio_controller_query_log_duration_seconds",
"Time in seconds log queries took to execute."
);
@@ -39,7 +32,7 @@ class ControlConnection extends BaseConnection {
/**
* The user making this connection.
* @type {module:lib/users.User}
* @type {module:lib.User}
*/
this.user = user;
@@ -103,75 +96,75 @@ class ControlConnection extends BaseConnection {
});
}
this.handle(libData.ControllerConfigGetRequest, this.handleControllerConfigGetRequest.bind(this));
this.handle(libData.ControllerConfigSetFieldRequest, this.handleControllerConfigSetFieldRequest.bind(this));
this.handle(libData.ControllerConfigSetPropRequest, this.handleControllerConfigSetPropRequest.bind(this));
this.handle(libData.HostListRequest, this.handleHostListRequest.bind(this));
this.handle(libData.HostSetSubscriptionsRequest, this.handleHostSetSubscriptionsRequest.bind(this));
this.handle(libData.HostGenerateTokenRequest, this.handleHostGenerateTokenRequest.bind(this));
this.handle(libData.HostConfigCreateRequest, this.handleHostConfigCreateRequest.bind(this));
this.handle(libData.InstanceDetailsGetRequest, this.handleInstanceDetailsGetRequest.bind(this));
this.handle(libData.InstanceDetailsListRequest, this.handleInstanceDetailsListRequest.bind(this));
this.handle(lib.ControllerConfigGetRequest, this.handleControllerConfigGetRequest.bind(this));
this.handle(lib.ControllerConfigSetFieldRequest, this.handleControllerConfigSetFieldRequest.bind(this));
this.handle(lib.ControllerConfigSetPropRequest, this.handleControllerConfigSetPropRequest.bind(this));
this.handle(lib.HostListRequest, this.handleHostListRequest.bind(this));
this.handle(lib.HostSetSubscriptionsRequest, this.handleHostSetSubscriptionsRequest.bind(this));
this.handle(lib.HostGenerateTokenRequest, this.handleHostGenerateTokenRequest.bind(this));
this.handle(lib.HostConfigCreateRequest, this.handleHostConfigCreateRequest.bind(this));
this.handle(lib.InstanceDetailsGetRequest, this.handleInstanceDetailsGetRequest.bind(this));
this.handle(lib.InstanceDetailsListRequest, this.handleInstanceDetailsListRequest.bind(this));
this.handle(
libData.InstanceDetailsSetSubscriptionsRequest, this.handleInstanceDetailsSetSubscriptionsRequest.bind(this)
lib.InstanceDetailsSetSubscriptionsRequest, this.handleInstanceDetailsSetSubscriptionsRequest.bind(this)
);
this.handle(libData.InstanceCreateRequest, this.handleInstanceCreateRequest.bind(this));
this.handle(libData.InstanceDeleteRequest, this.handleInstanceDeleteRequest.bind(this));
this.handle(libData.InstanceConfigGetRequest, this.handleInstanceConfigGetRequest.bind(this));
this.handle(libData.InstanceConfigSetFieldRequest, this.handleInstanceConfigSetFieldRequest.bind(this));
this.handle(libData.InstanceConfigSetPropRequest, this.handleInstanceConfigSetPropRequest.bind(this));
this.handle(libData.InstanceAssignRequest, this.handleInstanceAssignRequest.bind(this));
this.handle(lib.InstanceCreateRequest, this.handleInstanceCreateRequest.bind(this));
this.handle(lib.InstanceDeleteRequest, this.handleInstanceDeleteRequest.bind(this));
this.handle(lib.InstanceConfigGetRequest, this.handleInstanceConfigGetRequest.bind(this));
this.handle(lib.InstanceConfigSetFieldRequest, this.handleInstanceConfigSetFieldRequest.bind(this));
this.handle(lib.InstanceConfigSetPropRequest, this.handleInstanceConfigSetPropRequest.bind(this));
this.handle(lib.InstanceAssignRequest, this.handleInstanceAssignRequest.bind(this));
this.handle(
libData.InstanceSetSaveListSubscriptionsRequest,
lib.InstanceSetSaveListSubscriptionsRequest,
this.handleInstanceSetSaveListSubscriptionsRequest.bind(this)
);
this.handle(
libData.InstanceRenameSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller)
lib.InstanceRenameSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller)
);
this.handle(libData.InstanceCopySaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller));
this.handle(lib.InstanceCopySaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller));
this.handle(
libData.InstanceDeleteSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller)
lib.InstanceDeleteSaveRequest, this._controller.sendToHostByInstanceId.bind(this._controller)
);
this.handle(libData.InstanceDownloadSaveRequest, this.handleInstanceDownloadSaveRequest.bind(this));
this.handle(libData.InstanceTransferSaveRequest, this.handleInstanceTransferSaveRequest.bind(this));
this.handle(libData.ModPackListRequest, this.handleModPackListRequest.bind(this));
this.handle(libData.ModPackSetSubscriptionsRequest, this.handleModPackSetSubscriptionsRequest.bind(this));
this.handle(libData.ModPackCreateRequest, this.handleModPackCreateRequest.bind(this));
this.handle(libData.ModPackUpdateRequest, this.handleModPackUpdateRequest.bind(this));
this.handle(libData.ModPackDeleteRequest, this.handleModPackDeleteRequest.bind(this));
this.handle(libData.ModGetRequest, this.handleModGetRequest.bind(this));
this.handle(libData.ModListRequest, this.handleModListRequest.bind(this));
this.handle(libData.ModSearchRequest, this.handleModSearchRequest.bind(this));
this.handle(libData.ModSetSubscriptionsRequest, this.handleModSetSubscriptionsRequest.bind(this));
this.handle(libData.ModDownloadRequest, this.handleModDownloadRequest.bind(this));
this.handle(libData.ModDeleteRequest, this.handleModDeleteRequest.bind(this));
this.handle(libData.LogSetSubscriptionsRequest, this.handleLogSetSubscriptionsRequest.bind(this));
this.handle(libData.LogQueryRequest, this.handleLogQueryRequest.bind(this));
this.handle(libData.PermissionListRequest, this.handlePermissionListRequest.bind(this));
this.handle(libData.RoleListRequest, this.handleRoleListRequest.bind(this));
this.handle(libData.RoleCreateRequest, this.handleRoleCreateRequest.bind(this));
this.handle(libData.RoleUpdateRequest, this.handleRoleUpdateRequest.bind(this));
this.handle(lib.InstanceDownloadSaveRequest, this.handleInstanceDownloadSaveRequest.bind(this));
this.handle(lib.InstanceTransferSaveRequest, this.handleInstanceTransferSaveRequest.bind(this));
this.handle(lib.ModPackListRequest, this.handleModPackListRequest.bind(this));
this.handle(lib.ModPackSetSubscriptionsRequest, this.handleModPackSetSubscriptionsRequest.bind(this));
this.handle(lib.ModPackCreateRequest, this.handleModPackCreateRequest.bind(this));
this.handle(lib.ModPackUpdateRequest, this.handleModPackUpdateRequest.bind(this));
this.handle(lib.ModPackDeleteRequest, this.handleModPackDeleteRequest.bind(this));
this.handle(lib.ModGetRequest, this.handleModGetRequest.bind(this));
this.handle(lib.ModListRequest, this.handleModListRequest.bind(this));
this.handle(lib.ModSearchRequest, this.handleModSearchRequest.bind(this));
this.handle(lib.ModSetSubscriptionsRequest, this.handleModSetSubscriptionsRequest.bind(this));
this.handle(lib.ModDownloadRequest, this.handleModDownloadRequest.bind(this));
this.handle(lib.ModDeleteRequest, this.handleModDeleteRequest.bind(this));
this.handle(lib.LogSetSubscriptionsRequest, this.handleLogSetSubscriptionsRequest.bind(this));
this.handle(lib.LogQueryRequest, this.handleLogQueryRequest.bind(this));
this.handle(lib.PermissionListRequest, this.handlePermissionListRequest.bind(this));
this.handle(lib.RoleListRequest, this.handleRoleListRequest.bind(this));
this.handle(lib.RoleCreateRequest, this.handleRoleCreateRequest.bind(this));
this.handle(lib.RoleUpdateRequest, this.handleRoleUpdateRequest.bind(this));
this.handle(
libData.RoleGrantDefaultPermissionsRequest, this.handleRoleGrantDefaultPermissionsRequest.bind(this)
lib.RoleGrantDefaultPermissionsRequest, this.handleRoleGrantDefaultPermissionsRequest.bind(this)
);
this.handle(libData.RoleDeleteRequest, this.handleRoleDeleteRequest.bind(this));
this.handle(libData.UserGetRequest, this.handleUserGetRequest.bind(this));
this.handle(libData.UserListRequest, this.handleUserListRequest.bind(this));
this.handle(libData.UserSetSubscriptionsRequest, this.handleUserSetSubscriptionsRequest.bind(this));
this.handle(libData.UserCreateRequest, this.handleUserCreateRequest.bind(this));
this.handle(libData.UserRevokeTokenRequest, this.handleUserRevokeTokenRequest.bind(this));
this.handle(libData.UserUpdateRolesRequest, this.handleUserUpdateRolesRequest.bind(this));
this.handle(libData.UserSetAdminRequest, this.handleUserSetAdminRequest.bind(this));
this.handle(libData.UserSetBannedRequest, this.handleUserSetBannedRequest.bind(this));
this.handle(libData.UserSetWhitelistedRequest, this.handleUserSetWhitelistedRequest.bind(this));
this.handle(libData.UserDeleteRequest, this.handleUserDeleteRequest.bind(this));
this.handle(libData.DebugDumpWsRequest, this.handleDebugDumpWsRequest.bind(this));
this.handle(lib.RoleDeleteRequest, this.handleRoleDeleteRequest.bind(this));
this.handle(lib.UserGetRequest, this.handleUserGetRequest.bind(this));
this.handle(lib.UserListRequest, this.handleUserListRequest.bind(this));
this.handle(lib.UserSetSubscriptionsRequest, this.handleUserSetSubscriptionsRequest.bind(this));
this.handle(lib.UserCreateRequest, this.handleUserCreateRequest.bind(this));
this.handle(lib.UserRevokeTokenRequest, this.handleUserRevokeTokenRequest.bind(this));
this.handle(lib.UserUpdateRolesRequest, this.handleUserUpdateRolesRequest.bind(this));
this.handle(lib.UserSetAdminRequest, this.handleUserSetAdminRequest.bind(this));
this.handle(lib.UserSetBannedRequest, this.handleUserSetBannedRequest.bind(this));
this.handle(lib.UserSetWhitelistedRequest, this.handleUserSetWhitelistedRequest.bind(this));
this.handle(lib.UserDeleteRequest, this.handleUserDeleteRequest.bind(this));
this.handle(lib.DebugDumpWsRequest, this.handleDebugDumpWsRequest.bind(this));
}
validateIngress(message) {
let origin = this.connector.dst;
if (origin.type !== message.src.type || origin.id !== message.src.id) {
throw new libErrors.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`);
throw new lib.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`);
}
}
@@ -179,7 +172,7 @@ class ControlConnection extends BaseConnection {
try {
this.checkPermission(message, entry);
} catch (err) {
this.connector.sendResponseError(new libData.ResponseError(err.message, err.code), message.src);
this.connector.sendResponseError(new lib.ResponseError(err.message, err.code), message.src);
logger.audit(`Permission denied for ${message.name} by ${this.user.name} from ${this.connector.dst}`);
throw err;
}
@@ -213,7 +206,7 @@ class ControlConnection extends BaseConnection {
}
async handleControllerConfigGetRequest() {
return new libData.RawConfig(this._controller.config.serialize("control"));
return new lib.RawConfig(this._controller.config.serialize("control"));
}
async handleControllerConfigSetFieldRequest(request) {
@@ -228,7 +221,7 @@ class ControlConnection extends BaseConnection {
async handleHostListRequest() {
let list = [];
for (let host of this._controller.hosts.values()) {
list.push(new libData.HostDetails(
list.push(new lib.HostDetails(
host.agent,
host.version,
host.name,
@@ -249,7 +242,7 @@ class ControlConnection extends BaseConnection {
this.hostSubscriptions.all
|| this.hostSubscriptions.hostIds.includes(host.id)
) {
this.send(new libData.HostUpdateEvent(update));
this.send(new lib.HostUpdateEvent(update));
}
}
@@ -262,7 +255,7 @@ class ControlConnection extends BaseConnection {
}
async handleHostConfigCreateRequest(request) {
let hostConfig = new libConfig.HostConfig("control");
let hostConfig = new lib.HostConfig("control");
await hostConfig.init();
hostConfig.set("host.controller_url", this._controller.getControllerUrl());
@@ -276,13 +269,13 @@ class ControlConnection extends BaseConnection {
this.user.checkPermission("core.host.generate_token");
hostConfig.set("host.controller_token", this._controller.generateHostToken(hostConfig.get("host.id")));
}
return new libData.RawConfig(hostConfig.serialize());
return new lib.RawConfig(hostConfig.serialize());
}
async handleInstanceDetailsGetRequest(request) {
let instance = this._controller.getRequestInstance(request.instanceId);
return new libData.InstanceDetails(
return new lib.InstanceDetails(
instance.config.get("instance.name"),
instance.id,
instance.config.get("instance.assigned_host"),
@@ -294,7 +287,7 @@ class ControlConnection extends BaseConnection {
async handleInstanceDetailsListRequest() {
let list = [];
for (let instance of this._controller.instances.values()) {
list.push(new libData.InstanceDetails(
list.push(new lib.InstanceDetails(
instance.config.get("instance.name"),
instance.id,
instance.config.get("instance.assigned_host"),
@@ -314,8 +307,8 @@ class ControlConnection extends BaseConnection {
this.instanceSubscriptions.all
|| this.instanceSubscriptions.instanceIds.includes(instance.id)
) {
this.send(new libData.InstanceDetailsUpdateEvent(
new libData.InstanceDetails(
this.send(new lib.InstanceDetailsUpdateEvent(
new lib.InstanceDetails(
instance.config.get("instance.name"),
instance.id,
instance.config.get("instance.assigned_host"),
@@ -328,7 +321,7 @@ class ControlConnection extends BaseConnection {
// XXX should probably add a hook for host reuqests?
async handleInstanceCreateRequest(request) {
let instanceConfig = new libConfig.InstanceConfig("controller");
let instanceConfig = new lib.InstanceConfig("controller");
await instanceConfig.load(request.config);
await this._controller.instanceCreate(instanceConfig);
}
@@ -339,18 +332,18 @@ class ControlConnection extends BaseConnection {
async handleInstanceConfigGetRequest(request) {
let instance = this._controller.getRequestInstance(request.instanceId);
return new libData.InstanceConfigGetRequest.Response(instance.config.serialize("control"));
return new lib.InstanceConfigGetRequest.Response(instance.config.serialize("control"));
}
async handleInstanceConfigSetFieldRequest(request) {
let instance = this._controller.getRequestInstance(request.instanceId);
if (request.field === "instance.assigned_host") {
throw new libErrors.RequestError("instance.assigned_host must be set through the assign-host interface");
throw new lib.RequestError("instance.assigned_host must be set through the assign-host interface");
}
if (request.field === "instance.id") {
// XXX is this worth implementing? It's race condition galore.
throw new libErrors.RequestError("Setting instance.id is not supported");
throw new lib.RequestError("Setting instance.id is not supported");
}
instance.config.set(request.field, request.value, "control");
@@ -377,7 +370,7 @@ class ControlConnection extends BaseConnection {
this.saveListSubscriptions.all
|| this.saveListSubscriptions.instanceIds.includes(instanceId)
) {
this.send(new libData.InstanceSaveListUpdateEvent(instanceId, saves));
this.send(new lib.InstanceSaveListUpdateEvent(instanceId, saves));
}
}
@@ -389,12 +382,12 @@ class ControlConnection extends BaseConnection {
let ready = new Promise((resolve, reject) => {
stream.events.on("source", resolve);
stream.events.on("timeout", () => reject(
new libErrors.RequestError("Timed out establishing stream from host")
new lib.RequestError("Timed out establishing stream from host")
));
});
ready.catch(() => {});
await this._controller.sendToHostByInstanceId(new libData.InstancePushSaveRequest(
await this._controller.sendToHostByInstanceId(new lib.InstancePushSaveRequest(
instanceId,
stream.id,
name,
@@ -406,17 +399,17 @@ class ControlConnection extends BaseConnection {
async handleInstanceTransferSaveRequest(request) {
if (request.sourceInstanceId === request.targetInstanceId) {
throw new libErrors.RequestError("Source and target instance may not be the same");
throw new lib.RequestError("Source and target instance may not be the same");
}
let sourceInstance = this._controller.getRequestInstance(request.sourceInstanceId);
let targetInstance = this._controller.getRequestInstance(request.targetInstanceId);
let sourceHostId = sourceInstance.config.get("instance.assigned_host");
let targetHostId = targetInstance.config.get("instance.assigned_host");
if (sourceHostId === null) {
throw new libErrors.RequestError("Source instance is not assigned a host");
throw new lib.RequestError("Source instance is not assigned a host");
}
if (targetHostId === null) {
throw new libErrors.RequestError("Target instance is not assigned a host");
throw new lib.RequestError("Target instance is not assigned a host");
}
// Let host handle request if source and target is on the same host.
@@ -427,12 +420,12 @@ class ControlConnection extends BaseConnection {
// Check connectivity
let sourceHostConnection = this._controller.wsServer.hostConnections.get(sourceHostId);
if (!sourceHostConnection || sourceHostConnection.closing) {
throw new libErrors.RequestError("Source host is not connected to the controller");
throw new lib.RequestError("Source host is not connected to the controller");
}
let targetHostConnection = this._controller.wsServer.hostConnections.get(targetHostId);
if (!targetHostConnection || targetHostConnection.closing) {
throw new libErrors.RequestError("Target host is not connected to the controller");
throw new lib.RequestError("Target host is not connected to the controller");
}
// Create stream to proxy from target to source
@@ -441,7 +434,7 @@ class ControlConnection extends BaseConnection {
if (stream.source) {
stream.source.destroy();
}
stream.events.emit("error", new libErrors.RequestError("Timed out establishing transfer stream"));
stream.events.emit("error", new lib.RequestError("Timed out establishing transfer stream"));
});
// Ignore errors if not listening for them to avoid crash.
@@ -452,7 +445,7 @@ class ControlConnection extends BaseConnection {
await Promise.all([
this._controller.sendTo(
{ hostId: sourceHostId },
new libData.InstancePushSaveRequest(request.sourceInstanceId, stream.id, request.sourceName),
new lib.InstancePushSaveRequest(request.sourceInstanceId, stream.id, request.sourceName),
),
events.once(stream.events, "source"),
]);
@@ -460,14 +453,14 @@ class ControlConnection extends BaseConnection {
// Establish pull from target host to stream and wait for completion.
let storedName = await this._controller.sendTo(
{ hostId: targetHostId },
new libData.InstancePullSaveRequest(request.targetInstanceId, stream.id, request.targetName),
new lib.InstancePullSaveRequest(request.targetInstanceId, stream.id, request.targetName),
);
// Delete source save if this is not a copy
if (!request.copy) {
await this._controller.sendTo(
{ hostId: sourceHostId },
new libData.InstanceDeleteSaveRequest(request.sourceInstanceId, request.sourceName),
new lib.InstanceDeleteSaveRequest(request.sourceInstanceId, request.sourceName),
);
}
@@ -485,7 +478,7 @@ class ControlConnection extends BaseConnection {
async handleModPackCreateRequest(request) {
let modPack = request.modPack;
if (this._controller.modPacks.has(modPack.id)) {
throw new libErrors.RequestError(`Mod pack with ID ${modPack.id} already exist`);
throw new lib.RequestError(`Mod pack with ID ${modPack.id} already exist`);
}
this._controller.modPacks.set(modPack.id, modPack);
this._controller.modPackUpdated(modPack);
@@ -494,7 +487,7 @@ class ControlConnection extends BaseConnection {
async handleModPackUpdateRequest(request) {
let modPack = request.modPack;
if (!this._controller.modPacks.has(modPack.id)) {
throw new libErrors.RequestError(`Mod pack with ID ${modPack.id} does not exist`);
throw new lib.RequestError(`Mod pack with ID ${modPack.id} does not exist`);
}
this._controller.modPacks.set(modPack.id, modPack);
this._controller.modPackUpdated(modPack);
@@ -504,7 +497,7 @@ class ControlConnection extends BaseConnection {
let { id } = request;
let modPack = this._controller.modPacks.get(id);
if (!modPack) {
throw new libErrors.RequestError(`Mod pack with ID ${id} does not exist`);
throw new lib.RequestError(`Mod pack with ID ${id} does not exist`);
}
modPack.isDeleted = true;
this._controller.modPacks.delete(id);
@@ -516,7 +509,7 @@ class ControlConnection extends BaseConnection {
this.modPackSubscriptions.all
|| this.modPackSubscriptions.modPackIds.includes(modPack.id)
) {
this.send(new libData.ModPackUpdateEvent(modPack));
this.send(new lib.ModPackUpdateEvent(modPack));
}
}
@@ -525,7 +518,7 @@ class ControlConnection extends BaseConnection {
let filename = `${name}_${version}.zip`;
let mod = this._controller.mods.get(filename);
if (!mod) {
throw new libErrors.RequestError(`Mod ${filename} does not exist`);
throw new lib.RequestError(`Mod ${filename} does not exist`);
}
return mod;
}
@@ -537,14 +530,14 @@ class ControlConnection extends BaseConnection {
static termsMatchesMod(terms, mod) {
for (let term of terms) {
if (term.type === "word") {
if (!libHelpers.wordMatches(term,
if (!lib.wordMatches(term,
mod.name, mod.version, mod.title, mod.author, mod.contact,
mod.homepage, mod.description, mod.filename
)) {
return false;
}
} else if (term.type === "attribute") {
if (!libHelpers.wordMatches(term.value, mod[term.name])) {
if (!lib.wordMatches(term.value, mod[term.name])) {
return false;
}
}
@@ -553,7 +546,7 @@ class ControlConnection extends BaseConnection {
}
async handleModSearchRequest(request) {
let query = libHelpers.parseSearchString(request.query, {
let query = lib.parseSearchString(request.query, {
name: "word",
// version
title: "word",
@@ -601,7 +594,7 @@ class ControlConnection extends BaseConnection {
author: (a, b) => strcmp(a.versions[0].author, b.versions[0].author),
};
if (!Object.prototype.hasOwnProperty.call(sorters, sort)) {
throw new libErrors.RequestError(`Invalid value for sort: ${sort}`);
throw new lib.RequestError(`Invalid value for sort: ${sort}`);
}
resultList.sort(sorters[sort]);
let order = request.sortOrder;
@@ -631,7 +624,7 @@ class ControlConnection extends BaseConnection {
let filename = `${name}_${version}.zip`;
let mod = this._controller.mods.get(filename);
if (!mod) {
throw new libErrors.RequestError(`Mod ${filename} does not exist`);
throw new lib.RequestError(`Mod ${filename} does not exist`);
}
let modPath = path.join(this._controller.config.get("controller.mods_directory"), mod.filename);
@@ -658,7 +651,7 @@ class ControlConnection extends BaseConnection {
this.modSubscriptions.all
|| this.modSubscriptions.modNames.includes(mod.name)
) {
this.send(new libData.ModUpdateEvent(mod));
this.send(new lib.ModUpdateEvent(mod));
}
}
@@ -666,7 +659,7 @@ class ControlConnection extends BaseConnection {
let { all, controller, hostIds, instanceIds } = this.logSubscriptions;
if (all || controller || hostIds.length || instanceIds.length) {
if (!this.logTransport) {
this.logTransport = new libLoggingUtils.LinkTransport({ link: this });
this.logTransport = new lib.LinkTransport({ link: this });
this._controller.clusterLogger.add(this.logTransport);
}
this.logTransport.filter = logFilter(this.logSubscriptions);
@@ -694,8 +687,8 @@ class ControlConnection extends BaseConnection {
async handlePermissionListRequest() {
let list = [];
for (let permission of libUsers.permissions.values()) {
list.push(new libData.RawPermission(
for (let permission of lib.permissions.values()) {
list.push(new lib.RawPermission(
permission.name,
permission.title,
permission.description,
@@ -707,7 +700,7 @@ class ControlConnection extends BaseConnection {
async handleRoleListRequest() {
let list = [];
for (let role of this._controller.userManager.roles.values()) {
list.push(new libData.RawRole(
list.push(new lib.RawRole(
role.id,
role.name,
role.description,
@@ -722,7 +715,7 @@ class ControlConnection extends BaseConnection {
// Start at 5 to leave space for future default roles
let id = Math.max(5, lastId+1);
this._controller.userManager.roles.set(id, new libUsers.Role({ id, ...request }));
this._controller.userManager.roles.set(id, new lib.Role({ id, ...request }));
return id;
}
@@ -730,7 +723,7 @@ class ControlConnection extends BaseConnection {
let { id, name, description, permissions } = request;
let role = this._controller.userManager.roles.get(id);
if (!role) {
throw new libErrors.RequestError(`Role with ID ${id} does not exist`);
throw new lib.RequestError(`Role with ID ${id} does not exist`);
}
role.name = name;
@@ -742,7 +735,7 @@ class ControlConnection extends BaseConnection {
async handleRoleGrantDefaultPermissionsRequest(request) {
let role = this._controller.userManager.roles.get(request.id);
if (!role) {
throw new libErrors.RequestError(`Role with ID ${request.id} does not exist`);
throw new lib.RequestError(`Role with ID ${request.id} does not exist`);
}
role.grantDefaultPermissions();
@@ -753,7 +746,7 @@ class ControlConnection extends BaseConnection {
let id = request.id;
let role = this._controller.userManager.roles.get(id);
if (!role) {
throw new libErrors.RequestError(`Role with ID ${id} does not exist`);
throw new lib.RequestError(`Role with ID ${id} does not exist`);
}
this._controller.userManager.roles.delete(id);
@@ -767,10 +760,10 @@ class ControlConnection extends BaseConnection {
let name = request.name;
let user = this._controller.userManager.users.get(name);
if (!user) {
throw new libErrors.RequestError(`User ${name} does not exist`);
throw new lib.RequestError(`User ${name} does not exist`);
}
return new libData.RawUser(
return new lib.RawUser(
user.name,
[...user.roles].map(role => role.id),
[...user.instances],
@@ -787,7 +780,7 @@ class ControlConnection extends BaseConnection {
async handleUserListRequest() {
let list = [];
for (let user of this._controller.userManager.users.values()) {
list.push(new libData.RawUser(
list.push(new lib.RawUser(
user.name,
[...user.roles].map(role => role.id),
[...user.instances],
@@ -812,8 +805,8 @@ class ControlConnection extends BaseConnection {
this.userSubscriptions.all
|| this.userSubscriptions.names.includes(user.name)
) {
this.send(new libData.UserUpdateEvent(
new libData.RawUser(
this.send(new lib.UserUpdateEvent(
new lib.RawUser(
user.name,
[...user.roles].map(role => role.id),
[...user.instances],
@@ -837,7 +830,7 @@ class ControlConnection extends BaseConnection {
async handleUserRevokeTokenRequest(request) {
let user = this._controller.userManager.users.get(request.name);
if (!user) {
throw new libErrors.RequestError(`User '${request.name}' does not exist`);
throw new lib.RequestError(`User '${request.name}' does not exist`);
}
if (user.name !== this.user.name) {
this.user.checkPermission("core.user.revoke_other_token");
@@ -855,14 +848,14 @@ class ControlConnection extends BaseConnection {
async handleUserUpdateRolesRequest(request) {
let user = this._controller.userManager.users.get(request.name);
if (!user) {
throw new libErrors.RequestError(`User '${request.name}' does not exist`);
throw new lib.RequestError(`User '${request.name}' does not exist`);
}
let resolvedRoles = new Set();
for (let roleId of request.roles) {
let role = this._controller.userManager.roles.get(roleId);
if (!role) {
throw new libErrors.RequestError(`Role with ID ${roleId} does not exist`);
throw new lib.RequestError(`Role with ID ${roleId} does not exist`);
}
resolvedRoles.add(role);
@@ -881,13 +874,13 @@ class ControlConnection extends BaseConnection {
this.user.checkPermission("core.user.create");
user = this._controller.userManager.createUser(name);
} else {
throw new libErrors.RequestError(`User '${name}' does not exist`);
throw new lib.RequestError(`User '${name}' does not exist`);
}
}
user.isAdmin = admin;
this._controller.userUpdated(user);
this._controller.sendTo("allInstances", new libData.InstanceAdminlistUpdateEvent(name, admin));
this._controller.sendTo("allInstances", new lib.InstanceAdminlistUpdateEvent(name, admin));
}
async handleUserSetBannedRequest(request) {
@@ -898,14 +891,14 @@ class ControlConnection extends BaseConnection {
this.user.checkPermission("core.user.create");
user = this._controller.userManager.createUser(name);
} else {
throw new libErrors.RequestError(`User '${name}' does not exist`);
throw new lib.RequestError(`User '${name}' does not exist`);
}
}
user.isBanned = banned;
user.banReason = reason;
this._controller.userUpdated(user);
this._controller.sendTo("allInstances", new libData.InstanceBanlistUpdateEvent(name, banned, reason));
this._controller.sendTo("allInstances", new lib.InstanceBanlistUpdateEvent(name, banned, reason));
}
async handleUserSetWhitelistedRequest(request) {
@@ -916,20 +909,20 @@ class ControlConnection extends BaseConnection {
this.user.checkPermission("core.user.create");
user = this._controller.userManager.createUser(name);
} else {
throw new libErrors.RequestError(`User '${name}' does not exist`);
throw new lib.RequestError(`User '${name}' does not exist`);
}
}
user.isWhitelisted = whitelisted;
this._controller.userUpdated(user);
this._controller.sendTo("allInstances", new libData.InstanceWhitelistUpdateEvent(name, whitelisted));
this._controller.sendTo("allInstances", new lib.InstanceWhitelistUpdateEvent(name, whitelisted));
}
async handleUserDeleteRequest(request) {
let name = request.name;
let user = this._controller.userManager.users.get(name);
if (!user) {
throw new libErrors.RequestError(`User '${name}' does not exist`);
throw new lib.RequestError(`User '${name}' does not exist`);
}
user.isDeleted = true;
@@ -937,20 +930,20 @@ class ControlConnection extends BaseConnection {
this._controller.userUpdated(user);
if (user.is_admin) {
this._controller.sendTo("allInstances", new libData.InstanceAdminlistUpdateEvent(name, false));
this._controller.sendTo("allInstances", new lib.InstanceAdminlistUpdateEvent(name, false));
}
if (user.is_whitelisted) {
this._controller.sendTo("allInstances", new libData.InstanceWhitelistUpdateEvent(name, false));
this._controller.sendTo("allInstances", new lib.InstanceWhitelistUpdateEvent(name, false));
}
if (user.is_banned) {
this._controller.sendTo("allInstances", new libData.InstanceBanlistUpdateEvent(name, false, ""));
this._controller.sendTo("allInstances", new lib.InstanceBanlistUpdateEvent(name, false, ""));
}
}
async handleDebugDumpWsRequest(request) {
this.ws_dumper = data => {
if (this.connector.connected) {
this.send(new libData.DebugWsMessageEvent(data.direction, data.content));
this.send(new lib.DebugWsMessageEvent(data.direction, data.content));
}
};
this.connector._socket.clusterio_ignore_dump = true;
+76 -84
View File
@@ -9,16 +9,8 @@ const jwt = require("jsonwebtoken");
const path = require("path");
const stream = require("stream");
const libConfig = require("@clusterio/lib/config");
const libData = require("@clusterio/lib/data");
const libErrors = require("@clusterio/lib/errors");
const libFileOps = require("@clusterio/lib/file_ops");
const libLink = require("@clusterio/lib/link");
const libLoggingUtils = require("@clusterio/lib/logging_utils");
const libPlugin = require("@clusterio/lib/plugin");
const libPluginLoader = require("@clusterio/lib/plugin_loader");
const libPrometheus = require("@clusterio/lib/prometheus");
const { logger } = require("@clusterio/lib/logging");
const lib = require("@clusterio/lib");
const { logger } = lib;
const HttpCloser = require("./HttpCloser");
const InstanceInfo = require("./InstanceInfo");
@@ -28,13 +20,13 @@ const UserManager = require("./UserManager");
const WsServer = require("./WsServer");
const endpointDurationSummary = new libPrometheus.Summary(
const endpointDurationSummary = new lib.Summary(
"clusterio_controller_http_endpoint_duration_seconds",
"Time it took to respond to a an HTTP request",
{ labels: ["route"] }
);
const logSizeGauge = new libPrometheus.Gauge(
const logSizeGauge = new lib.Gauge(
"clusterio_controller_log_bytes",
"Size of all log files currently stored on the controller."
);
@@ -54,7 +46,7 @@ class Controller {
this.configPath = configPath;
/**
* Controller config.
* @type {module:lib/config.ControllerConfig}
* @type {module:lib.ControllerConfig}
*/
this.config = config;
@@ -76,13 +68,13 @@ class Controller {
/**
* Mapping of mod pack id to mod pack
* @type {Map<number, module:lib/data.ModPack>}
* @type {Map<number, module:lib.ModPack>}
*/
this.modPacks = null;
/**
* Mapping of mod names to mod infos
* @type {Map<string, module:lib/data.ModInfo>}
* @type {Map<string, module:lib.ModInfo>}
*/
this.mods = null;
@@ -98,7 +90,7 @@ class Controller {
/**
* Mapping of plugin name to loaded plugin
* @type {Map<string, module:lib/plugin.BaseControllerPlugin>}
* @type {Map<string, module:lib.BaseControllerPlugin>}
*/
this.plugins = new Map();
@@ -150,15 +142,15 @@ class Controller {
*/
async logSize() {
return (await Promise.all([
libFileOps.directorySize(path.join(this.logDirectory, "cluster")),
libFileOps.directorySize(path.join(this.logDirectory, "controller")),
libFileOps.directorySize(path.join(this.logDirectory, "host")),
lib.directorySize(path.join(this.logDirectory, "cluster")),
lib.directorySize(path.join(this.logDirectory, "controller")),
lib.directorySize(path.join(this.logDirectory, "host")),
])).reduce((a, v) => a + v, 0);
}
async _startInternal(args) {
this.logDirectory = args.logDirectory;
this.clusterLogIndex = await libLoggingUtils.LogIndex.load(path.join(this.logDirectory, "cluster"));
this.clusterLogIndex = await lib.LogIndex.load(path.join(this.logDirectory, "cluster"));
this.clusterLogBuildInterval = setInterval(() => {
this.clusterLogIndex.buildIndex().catch(
err => logger.error(`Error building cluster log index:\n${err.stack}`)
@@ -181,7 +173,7 @@ class Controller {
for (let name of args.devPlugin) {
let info = this.pluginInfos.find(i => i.name === name);
if (!info) {
throw new libErrors.StartupError(`No plugin named ${name}`);
throw new lib.StartupError(`No plugin named ${name}`);
}
let config = require(path.posix.join(info.requirePath, "webpack.config"))({});
devPlugins.set(name, webpackConfigs.length);
@@ -210,7 +202,7 @@ class Controller {
this.mods = await Controller.loadModInfos(modsDirectory);
this.config.on("fieldChanged", (group, field, prev) => {
libPlugin.invokeHook(this.plugins, "onControllerConfigFieldChanged", group, field, prev);
lib.invokeHook(this.plugins, "onControllerConfigFieldChanged", group, field, prev);
});
for (let instance of this.instances.values()) {
this.addInstanceHooks(instance);
@@ -230,7 +222,7 @@ class Controller {
let tls_key = this.config.get("controller.tls_private_key");
if (httpsPort && (!tls_cert || !tls_key)) {
throw new libErrors.StartupError(
throw new lib.StartupError(
"tls_certificate and tls_private_key must be configure in order to use https_port"
);
}
@@ -265,7 +257,7 @@ class Controller {
privateKey = await fs.readFile(tls_key);
} catch (err) {
throw new libErrors.StartupError(
throw new lib.StartupError(
`Error loading ssl certificate: ${err.message}`
);
}
@@ -313,7 +305,7 @@ class Controller {
}
logger.info("Saving config");
await libFileOps.safeOutputFile(this.configPath, JSON.stringify(this.config.serialize(), null, 4));
await lib.safeOutputFile(this.configPath, JSON.stringify(this.config.serialize(), null, 4));
if (this.devMiddleware) {
await new Promise((resolve, reject) => { this.devMiddleware.close(resolve); });
@@ -336,7 +328,7 @@ class Controller {
await this.userManager.save(path.join(databaseDirectory, "users.json"));
}
await libPlugin.invokeHook(this.plugins, "onShutdown");
await lib.invokeHook(this.plugins, "onShutdown");
if (this.wsServer) {
await this.wsServer.stop();
@@ -373,7 +365,7 @@ class Controller {
}
static async saveHosts(filePath, hosts) {
await libFileOps.safeOutputFile(filePath, JSON.stringify([...hosts.entries()], null, 4));
await lib.safeOutputFile(filePath, JSON.stringify([...hosts.entries()], null, 4));
}
static async loadInstances(filePath) {
@@ -383,7 +375,7 @@ class Controller {
try {
let serialized = JSON.parse(await fs.readFile(filePath));
for (let serializedConfig of serialized) {
let instanceConfig = new libConfig.InstanceConfig("controller");
let instanceConfig = new lib.InstanceConfig("controller");
await instanceConfig.load(serializedConfig);
let status = instanceConfig.get("instance.assigned_host") === null ? "unassigned" : "unknown";
let instance = new InstanceInfo({ config: instanceConfig, status });
@@ -405,7 +397,7 @@ class Controller {
serialized.push(instance.config.serialize());
}
await libFileOps.safeOutputFile(filePath, JSON.stringify(serialized, null, 4));
await lib.safeOutputFile(filePath, JSON.stringify(serialized, null, 4));
}
static async loadModPacks(filePath) {
@@ -418,11 +410,11 @@ class Controller {
}
return new Map();
}
return new Map(json.map(e => [e.id, libData.ModPack.fromJSON(e)]));
return new Map(json.map(e => [e.id, lib.ModPack.fromJSON(e)]));
}
static async saveModPacks(filePath, modPacks) {
await libFileOps.safeOutputFile(filePath, JSON.stringify([...modPacks.values()], null, 4));
await lib.safeOutputFile(filePath, JSON.stringify([...modPacks.values()], null, 4));
}
static async loadModInfos(modsDirectory) {
@@ -440,7 +432,7 @@ class Controller {
logger.info(`Loading info for Mod ${entry.name}`);
let modInfo;
try {
modInfo = await libData.ModInfo.fromModFile(path.join(modsDirectory, entry.name));
modInfo = await lib.ModInfo.fromModFile(path.join(modsDirectory, entry.name));
} catch (err) {
logger.error(`Error loading mod ${entry.name}: ${err.message}`);
continue;
@@ -488,13 +480,13 @@ class Controller {
/**
* Query controller log
*
* @param {module:lib/logging_utils~QueryLogFilter} filter -
* @param {module:lib~QueryLogFilter} filter -
* Filter to limit entries with. Note that only the controller log can
* be queried from this function.
* @returns {Promise<Array<Object>>} log entries matching the filter
*/
async queryControllerLog(filter) {
return await libLoggingUtils.queryLog(
return await lib.queryLog(
path.join(this.logDirectory, "controller"), filter,
);
}
@@ -502,12 +494,12 @@ class Controller {
/**
* Query cluster log
*
* @param {module:lib/logging_utils~QueryLogFilter} filter -
* @param {module:lib~QueryLogFilter} filter -
* Filter to limit entries with.
* @returns {Promise<Array<Object>>} log entries matching the filter
*/
async queryClusterLog(filter) {
return await libLoggingUtils.queryLog(
return await lib.queryLog(
path.join(this.logDirectory, "cluster"), filter, this.clusterLogIndex,
);
}
@@ -564,7 +556,7 @@ class Controller {
}
hostUpdated(host) {
let update = new libData.HostDetails(
let update = new lib.HostDetails(
host.agent,
host.version,
host.name,
@@ -587,12 +579,12 @@ class Controller {
*
* @param {number} instanceId - ID of instance to get.
* @returns {object} instance
* @throws {module:lib/errors.RequestError} if the instance does not exist.
* @throws {module:lib.RequestError} if the instance does not exist.
*/
getRequestInstance(instanceId) {
let instance = this.instances.get(instanceId);
if (!instance) {
throw new libErrors.RequestError(`Instance with ID ${instanceId} does not exist`);
throw new lib.RequestError(`Instance with ID ${instanceId} does not exist`);
}
return instance;
}
@@ -604,20 +596,20 @@ class Controller {
* creates an instance using that config in the cluster.
*
* @example
* let instanceConfig = new libConfig.InstanceConfig("controller");
* let instanceConfig = new lib.InstanceConfig("controller");
* await instanceConfig.init();
* instanceConfig.set("instance.name", "My instance");
* let instance = await controller.instanceAssign(instanceConfig);
* await controller.instanceAssign(instance.id, hostId);
*
* @param {module:lib/config.InstanceConfig} instanceConfig -
* @param {module:lib.InstanceConfig} instanceConfig -
* Config to base newly created instance on.
* @returns {module:controller/src/InstanceInfo} The created instance
*/
async instanceCreate(instanceConfig) {
let instanceId = instanceConfig.get("instance.id");
if (this.instances.has(instanceId)) {
throw new libErrors.RequestError(`Instance with ID ${instanceId} already exists`);
throw new lib.RequestError(`Instance with ID ${instanceId} already exists`);
}
// Add common settings for the Factorio server
@@ -648,7 +640,7 @@ class Controller {
let instance = new InstanceInfo({ config: instanceConfig, status: "unassigned" });
this.instances.set(instanceId, instance);
await libPlugin.invokeHook(this.plugins, "onInstanceStatusChanged", instance, null);
await lib.invokeHook(this.plugins, "onInstanceStatusChanged", instance, null);
this.addInstanceHooks(instance);
}
@@ -678,7 +670,7 @@ class Controller {
// target host be connected to the controller while doing the
// assignment, but it is IMHO a better user experience if this
// is the case.
throw new libErrors.RequestError("Target host is not connected to the controller");
throw new lib.RequestError("Target host is not connected to the controller");
}
}
@@ -687,7 +679,7 @@ class Controller {
if (currentAssignedHost !== null && hostId !== currentAssignedHost) {
let oldHostConnection = this.wsServer.hostConnections.get(currentAssignedHost);
if (oldHostConnection && !oldHostConnection.connector.closing) {
await oldHostConnection.send(new libData.InstanceUnassignInternalRequest(instanceId));
await oldHostConnection.send(new lib.InstanceUnassignInternalRequest(instanceId));
}
}
@@ -695,7 +687,7 @@ class Controller {
instance.config.set("instance.assigned_host", hostId);
if (hostId !== null) {
await newHostConnection.send(
new libData.InstanceAssignInternalRequest(instanceId, instance.config.serialize("host"))
new lib.InstanceAssignInternalRequest(instanceId, instance.config.serialize("host"))
);
} else {
instance.status = "unassigned";
@@ -715,14 +707,14 @@ class Controller {
let instance = this.getRequestInstance(instanceId);
let hostId = instance.config.get("instance.assigned_host");
if (hostId !== null) {
await this.sendTo({ hostId }, new libData.InstanceDeleteInternalRequest(instanceId));
await this.sendTo({ hostId }, new lib.InstanceDeleteInternalRequest(instanceId));
}
this.instances.delete(instanceId);
let prev = instance.status;
instance.status = "deleted";
this.instanceUpdated(instance);
await libPlugin.invokeHook(this.plugins, "onInstanceStatusChanged", instance, prev);
await lib.invokeHook(this.plugins, "onInstanceStatusChanged", instance, prev);
}
/**
@@ -740,7 +732,7 @@ class Controller {
let connection = this.wsServer.hostConnections.get(hostId);
if (connection) {
await connection.send(
new libData.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host"))
new lib.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host"))
);
}
}
@@ -752,7 +744,7 @@ class Controller {
this.instanceUpdated(instance);
}
libPlugin.invokeHook(this.plugins, "onInstanceConfigFieldChanged", instance, group, field, prev);
lib.invokeHook(this.plugins, "onInstanceConfigFieldChanged", instance, group, field, prev);
});
this.instanceUpdated(instance);
@@ -786,7 +778,7 @@ class Controller {
controlConnection.modPackUpdated(modPack);
}
libPlugin.invokeHook(this.plugins, "onModPackUpdated", modPack);
lib.invokeHook(this.plugins, "onModPackUpdated", modPack);
}
modUpdated(mod) {
@@ -798,7 +790,7 @@ class Controller {
controlConnection.modUpdated(mod);
}
libPlugin.invokeHook(this.plugins, "onModUpdated", mod);
lib.invokeHook(this.plugins, "onModUpdated", mod);
}
userUpdated(user) {
@@ -814,13 +806,13 @@ class Controller {
/**
* Notify connected control clients under the given user that the
* permissions for this user may have changed.
* @param {module:lib/users.User} user - User permisions updated for.
* @param {module:lib.User} user - User permisions updated for.
*/
userPermissionsUpdated(user) {
for (let controlConnection of this.wsServer.controlConnections.values()) {
if (controlConnection.user === user) {
controlConnection.send(
new libData.AccountUpdateEvent([...user.roles].map(r => ({
new lib.AccountUpdateEvent([...user.roles].map(r => ({
name: r.name,
id: r.id,
permissions: [...r.permissions],
@@ -833,13 +825,13 @@ class Controller {
/**
* Notify connected control clients with the given role that the
* permissions may have changed.
* @param {module:lib/users.Role} role - Role permisions updated for.
* @param {module:lib.Role} role - Role permisions updated for.
*/
rolePermissionsUpdated(role) {
for (let controlConnection of this.wsServer.controlConnections.values()) {
if (controlConnection.user.roles.has(role)) {
controlConnection.send(
new libData.AccountUpdateEvent(
new lib.AccountUpdateEvent(
[...controlConnection.user.roles].map(r => ({
name: r.name,
id: r.id,
@@ -864,10 +856,10 @@ class Controller {
continue;
}
let ControllerPluginClass = libPlugin.BaseControllerPlugin;
let ControllerPluginClass = lib.BaseControllerPlugin;
try {
if (pluginInfo.controllerEntrypoint) {
ControllerPluginClass = await libPluginLoader.loadControllerPluginClass(pluginInfo);
ControllerPluginClass = await lib.loadControllerPluginClass(pluginInfo);
}
let controllerPlugin = new ControllerPluginClass(pluginInfo, this, metrics, logger);
@@ -875,7 +867,7 @@ class Controller {
this.plugins.set(pluginInfo.name, controllerPlugin);
} catch (err) {
throw new libErrors.PluginError(pluginInfo.name, err);
throw new lib.PluginError(pluginInfo.name, err);
}
logger.info(`Loaded plugin ${pluginInfo.name}`);
@@ -899,7 +891,7 @@ class Controller {
});
function wrapError(err) {
reject(new libErrors.StartupError(
reject(new lib.StartupError(
`Server listening failed: ${err.message}`
));
}
@@ -982,7 +974,7 @@ class Controller {
}
handleRequest(Request, handler) {
if (!libLink.Link._requestsByClass.has(Request)) {
if (!lib.Link._requestsByClass.has(Request)) {
throw new Error(`Unregistered Request class ${Request.name}`);
}
if (this._registeredRequests.has(Request)) {
@@ -992,7 +984,7 @@ class Controller {
}
fallbackRequest(Request, handler) {
if (!libLink.Link._requestsByClass.has(Request)) {
if (!lib.Link._requestsByClass.has(Request)) {
throw new Error(`Unregistered Request class ${Request.name}`);
}
if (this._fallbackedRequests.has(Request)) {
@@ -1002,7 +994,7 @@ class Controller {
}
handleEvent(Event, handler) {
if (!libLink.Link._eventsByClass.has(Event)) {
if (!lib.Link._eventsByClass.has(Event)) {
throw new Error(`Unregistered Event class ${Event.name}`);
}
if (this._registeredEvents.has(Event)) {
@@ -1012,7 +1004,7 @@ class Controller {
}
snoopEvent(Event, handler) {
if (!libLink.Link._eventsByClass.has(Event)) {
if (!lib.Link._eventsByClass.has(Event)) {
throw new Error(`Unregistered Event class ${Event.name}`);
}
if (this._snoopedEvents.has(Event)) {
@@ -1026,16 +1018,16 @@ class Controller {
*
* Routes the given request or event to the given destination. The
* destination argument supports address shorthands, see {@link
* module:lib/data.Address.fromShorthand}
* module:lib.Address.fromShorthand}
*
* @param {*|module:lib/data.Address} address - Where to send it.
* @param {*|module:lib.Address} address - Where to send it.
* @param {*} requestOrEvent - The request or event to send.
* @returns {Promise<*>|undefined}
* Promise that resolves to the response if a request was sent or
* undefined if it was an event.
*/
sendTo(address, requestOrEvent) {
let dst = libData.Address.fromShorthand(address);
let dst = lib.Address.fromShorthand(address);
if (requestOrEvent.constructor.type === "request") {
return this.sendRequest(requestOrEvent, dst);
}
@@ -1047,30 +1039,30 @@ class Controller {
async sendRequest(request, dst) {
let connection;
if (dst.type === libData.Address.controller) {
if (dst.type === lib.Address.controller) {
throw new Error("controller as dst is not supported.");
} else if (dst.type === libData.Address.control) {
} else if (dst.type === lib.Address.control) {
connection = this.wsServer.controlConnections.get(dst.id);
if (!connection) {
throw new libErrors.RequestError("Target control connection does not exist.");
throw new lib.RequestError("Target control connection does not exist.");
}
} else if (dst.type === libData.Address.instance) {
} else if (dst.type === lib.Address.instance) {
let instance = this.getRequestInstance(dst.id);
let hostId = instance.config.get("instance.assigned_host");
if (hostId === null) {
throw new libErrors.RequestError("Instance is not assigned to a host");
throw new lib.RequestError("Instance is not assigned to a host");
}
connection = this.wsServer.hostConnections.get(hostId);
if (!connection) {
throw new libErrors.RequestError("Host containing instance is not connected");
throw new lib.RequestError("Host containing instance is not connected");
}
} else if (dst.type === libData.Address.host) {
} else if (dst.type === lib.Address.host) {
connection = this.wsServer.hostConnections.get(dst.id);
if (!connection) {
throw new libErrors.RequestError("Host is not connected");
throw new lib.RequestError("Host is not connected");
}
} else {
@@ -1082,13 +1074,13 @@ class Controller {
sendEvent(event, dst) {
let connection;
if (dst.type === libData.Address.controller) {
if (dst.type === lib.Address.controller) {
throw new Error("controller as dst is not supported.");
} else if (dst.type === libData.Address.control) {
} else if (dst.type === lib.Address.control) {
connection = this.wsServer.controlConnections.get(dst.id);
} else if (dst.type === libData.Address.instance) {
} else if (dst.type === lib.Address.instance) {
let instance = this.instances.get(dst.id);
if (!instance) {
return;
@@ -1099,16 +1091,16 @@ class Controller {
}
connection = this.wsServer.hostConnections.get(hostId);
} else if (dst.type === libData.Address.host) {
} else if (dst.type === lib.Address.host) {
connection = this.wsServer.hostConnections.get(dst.id);
} else if (dst.type === libData.Address.broadcast) {
if (dst.id === libData.Address.control) {
} else if (dst.type === lib.Address.broadcast) {
if (dst.id === lib.Address.control) {
for (let controlConnection of this.wsServer.controlConnections.values()) {
controlConnection.sendEvent(event, dst);
}
} else if (dst.id === libData.Address.instance || dst.id === libData.Address.host) {
} else if (dst.id === lib.Address.instance || dst.id === lib.Address.host) {
for (let hostConnection of this.wsServer.hostConnections.values()) {
hostConnection.sendEvent(event, dst);
}
@@ -1141,11 +1133,11 @@ class Controller {
let instance = this.getRequestInstance(request.instanceId);
let hostId = instance.config.get("instance.assigned_host");
if (hostId === null) {
throw new libErrors.RequestError("Instance is not assigned to a host");
throw new lib.RequestError("Instance is not assigned to a host");
}
let connection = this.wsServer.hostConnections.get(hostId);
if (!connection) {
throw new libErrors.RequestError("Host containing instance is not connected");
throw new lib.RequestError("Host containing instance is not connected");
}
return await connection.send(request);
}
+11 -11
View File
@@ -1,5 +1,5 @@
"use strict";
const libData = require("@clusterio/lib/data");
const lib = require("@clusterio/lib");
class ControllerRouter {
/** @type {module:controller/src/Controller} */
@@ -20,8 +20,8 @@ class ControllerRouter {
}
/**
* @param {module:lib/link.Link} origin - Source link of the message.
* @param {module:lib/data.Message} message
* @param {module:lib.Link} origin - Source link of the message.
* @param {module:lib.Message} message
* Link the message originated from.
* @param {boolean} hasFallback - true if fallback handling is available.
* @returns {boolean} true if the message was handled
@@ -34,15 +34,15 @@ class ControllerRouter {
let dst = message.dst;
let nextHop;
let msg;
if (dst.type === libData.Address.broadcast) {
if (dst.type === lib.Address.broadcast) {
this.broadcastMessage(origin, message);
return true;
} else if (dst.type === libData.Address.host) {
} else if (dst.type === lib.Address.host) {
nextHop = this.controller.wsServer.hostConnections.get(dst.id);
if (!nextHop) {
msg = `Host ${dst.id} is offline`;
}
} else if (dst.type === libData.Address.instance) {
} else if (dst.type === lib.Address.instance) {
let instance = this.controller.instances.get(dst.id);
if (!instance) {
msg = `Instance ${dst.id} does not exist`;
@@ -57,12 +57,12 @@ class ControllerRouter {
}
}
}
} else if (dst.type === libData.Address.control) {
} else if (dst.type === lib.Address.control) {
nextHop = this.controller.wsServer.controlConnections.get(dst.id);
if (!nextHop) {
msg = "Control connection does not exist";
}
} else if (dst.type === libData.Address.controller) {
} else if (dst.type === lib.Address.controller) {
msg = `Unexpected message forwarded to ${dst}`;
}
@@ -77,7 +77,7 @@ class ControllerRouter {
return false;
}
origin.connector.sendResponseError(
new libData.ResponseError(msg || "Unroutable destination"), message.src
new lib.ResponseError(msg || "Unroutable destination"), message.src
);
return true;
}
@@ -100,13 +100,13 @@ class ControllerRouter {
let dst = message.dst;
if (message.type !== "event") {
this.warnUnrouted(message, `Unexpected broadcast of ${message.type}`);
} else if (dst.id === libData.Address.host || dst.id === libData.Address.instance) {
} else if (dst.id === lib.Address.host || dst.id === lib.Address.instance) {
for (let hostConnection of this.controller.wsServer.hostConnections.values()) {
if (hostConnection !== origin) {
hostConnection.connector.send(message);
}
}
} else if (dst.id === libData.Address.control) {
} else if (dst.id === lib.Address.control) {
for (let controlConnection of this.controller.wsServer.controlConnections.values()) {
if (controlConnection !== origin) {
controlConnection.connector.send(message);
+25 -29
View File
@@ -1,10 +1,6 @@
"use strict";
const libData = require("@clusterio/lib/data");
const libConfig = require("@clusterio/lib/config");
const libErrors = require("@clusterio/lib/errors");
const { logger } = require("@clusterio/lib/logging");
const libPlugin = require("@clusterio/lib/plugin");
const PlayerStats = require("@clusterio/lib/PlayerStats");
const lib = require("@clusterio/lib");
const { logger, PlayerStats } = lib;
const BaseConnection = require("./BaseConnection");
const InstanceInfo = require("./InstanceInfo");
@@ -55,36 +51,36 @@ class HostConnection extends BaseConnection {
let prev = instance.status;
instance.status = "unknown";
this._controller.instanceUpdated(instance);
libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev);
lib.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev);
}
});
this.handle(libData.InstanceStatusChangedEvent, this.handleInstanceStatusChangedEvent.bind(this));
this.handle(libData.InstancesUpdateRequest, this.handleInstancesUpdateRequest.bind(this));
this.handle(libData.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this));
this.handle(libData.LogMessageEvent, this.handleLogMessageEvent.bind(this));
this.handle(libData.InstancePlayerUpdateEvent, this.handleInstancePlayerUpdateEvent.bind(this));
this.handle(lib.InstanceStatusChangedEvent, this.handleInstanceStatusChangedEvent.bind(this));
this.handle(lib.InstancesUpdateRequest, this.handleInstancesUpdateRequest.bind(this));
this.handle(lib.InstanceSaveListUpdateEvent, this.handleInstanceSaveListUpdateEvent.bind(this));
this.handle(lib.LogMessageEvent, this.handleLogMessageEvent.bind(this));
this.handle(lib.InstancePlayerUpdateEvent, this.handleInstancePlayerUpdateEvent.bind(this));
}
validateIngress(message) {
let origin = this.connector.dst;
switch (message.src.type) {
case libData.Address.control:
case libData.Address.controller:
throw new libErrors.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`);
case lib.Address.control:
case lib.Address.controller:
throw new lib.InvalidMessage(`Received message with invalid src ${message.src} from ${origin}`);
case libData.Address.host:
case lib.Address.host:
if (message.src.id !== origin.id) {
throw new libErrors.InvalidMessage(
throw new lib.InvalidMessage(
`Received message with invalid src ${message.src} from ${origin}`
);
}
break;
case libData.Address.instance:
case lib.Address.instance:
let instance = this._controller.instances.get(message.src.id);
if (!instance || instance.config.get("instance.assigned_host") !== this._id) {
throw new libErrors.InvalidMessage(
throw new lib.InvalidMessage(
`Received message with invalid src ${message.src} from ${origin}`
);
}
@@ -120,7 +116,7 @@ class HostConnection extends BaseConnection {
}
async prepareDisconnect() {
await libPlugin.invokeHook(this._controller.plugins, "onPrepareHostDisconnect", this);
await lib.invokeHook(this._controller.plugins, "onPrepareHostDisconnect", this);
return await super.prepareDisconnect();
}
@@ -159,7 +155,7 @@ class HostConnection extends BaseConnection {
instance.game_port = request.gamePort;
logger.verbose(`Instance ${instance.config.get("instance.name")} State: ${instance.status}`);
this._controller.instanceUpdated(instance);
await libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev);
await lib.invokeHook(this._controller.plugins, "onInstanceStatusChanged", instance, prev);
}
async handleInstancesUpdateRequest(request) {
@@ -167,14 +163,14 @@ class HostConnection extends BaseConnection {
for (let instance of this._controller.instances.values()) {
if (instance.config.get("instance.assigned_host") === this._id) {
await this.send(
new libData.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host"))
new lib.InstanceAssignInternalRequest(instance.id, instance.config.serialize("host"))
);
}
}
// Assign instances the host has but controller does not
for (let instanceData of request.instances) {
let instanceConfig = new libConfig.InstanceConfig("controller");
let instanceConfig = new lib.InstanceConfig("controller");
await instanceConfig.load(instanceData.config, "host");
let controllerInstance = this._controller.instances.get(instanceConfig.get("instance.id"));
@@ -182,7 +178,7 @@ class HostConnection extends BaseConnection {
// Check if this instance is assigned somewhere else.
if (controllerInstance.config.get("instance.assigned_host") !== this._id) {
await this.send(
new libData.InstanceUnassignInternalRequest(instanceConfig.get("instance.id"))
new lib.InstanceUnassignInternalRequest(instanceConfig.get("instance.id"))
);
continue;
}
@@ -193,7 +189,7 @@ class HostConnection extends BaseConnection {
controllerInstance.status = instanceData.status;
logger.verbose(`Instance ${instanceConfig.get("instance.name")} State: ${instanceData.status}`);
this._controller.instanceUpdated(controllerInstance);
await libPlugin.invokeHook(
await lib.invokeHook(
this._controller.plugins, "onInstanceStatusChanged", controllerInstance, prev
);
}
@@ -205,11 +201,11 @@ class HostConnection extends BaseConnection {
this._controller.instances.set(instanceConfig.get("instance.id"), newInstance);
this._controller.addInstanceHooks(newInstance);
await this.send(
new libData.InstanceAssignInternalRequest(
new lib.InstanceAssignInternalRequest(
instanceConfig.get("instance.id"), instanceConfig.serialize("host")
)
);
await libPlugin.invokeHook(this._controller.plugins, "onInstanceStatusChanged", newInstance, null);
await lib.invokeHook(this._controller.plugins, "onInstanceStatusChanged", newInstance, null);
}
// Push lists to make sure they are in sync.
@@ -229,7 +225,7 @@ class HostConnection extends BaseConnection {
}
}
await this.send(new libData.SyncUserListsEvent(adminlist, banlist, whitelist));
await this.send(new lib.SyncUserListsEvent(adminlist, banlist, whitelist));
}
async handleInstanceSaveListUpdateEvent(event) {
@@ -261,7 +257,7 @@ class HostConnection extends BaseConnection {
this._controller.userUpdated(user);
let instance = this._controller.instances.get(instanceId);
await libPlugin.invokeHook(this._controller.plugins, "onPlayerEvent", instance, {
await lib.invokeHook(this._controller.plugins, "onPlayerEvent", instance, {
type: event.type,
name: event.name,
reason: event.reason,
+1 -1
View File
@@ -5,7 +5,7 @@
* @alias module:controller/src/InstanceInfo
*/
class InstanceInfo {
/** @type {module:lib/config.InstanceConfig} */
/** @type {module:lib.InstanceConfig} */
config;
/**
+8 -9
View File
@@ -1,8 +1,7 @@
"use strict";
const fs = require("fs-extra");
const libFileOps = require("@clusterio/lib/file_ops");
const libUsers = require("@clusterio/lib/users");
const lib = require("@clusterio/lib");
/**
* Manages users and roles
@@ -21,12 +20,12 @@ class UserManager {
try {
let content = JSON.parse(await fs.readFile(filePath));
for (let serializedRole of content.roles) {
let role = new libUsers.Role(serializedRole);
let role = new lib.Role(serializedRole);
loadedRoles.set(role.id, role);
}
for (let serializedUser of content.users) {
let user = new libUsers.User(serializedUser, loadedRoles);
let user = new lib.User(serializedUser, loadedRoles);
loadedUsers.set(user.name, user);
}
@@ -36,8 +35,8 @@ class UserManager {
}
// Create default roles if loading failed
libUsers.ensureDefaultAdminRole(loadedRoles);
libUsers.ensureDefaultPlayerRole(loadedRoles);
lib.ensureDefaultAdminRole(loadedRoles);
lib.ensureDefaultPlayerRole(loadedRoles);
}
this.roles = loadedRoles;
@@ -63,7 +62,7 @@ class UserManager {
users: serializedUsers,
roles: serializedRoles,
};
await libFileOps.safeOutputFile(filePath, JSON.stringify(serialized, null, 4));
await lib.safeOutputFile(filePath, JSON.stringify(serialized, null, 4));
}
/**
@@ -72,7 +71,7 @@ class UserManager {
* Creates a new user and add it to the user database.
*
* @param {string} name - Name of the user to create.
* @returns {module:lib/users.User} newly created user.
* @returns {module:lib.User} newly created user.
*/
createUser(name) {
if (this.users.has(name)) {
@@ -80,7 +79,7 @@ class UserManager {
}
let defaultRoleId = this._config.get("controller.default_role_id");
let user = new libUsers.User({ name, roles: [defaultRoleId] }, this.roles);
let user = new lib.User({ name, roles: [defaultRoleId] }, this.roles);
this.users.set(name, user);
return user;
}
+15 -17
View File
@@ -2,10 +2,8 @@
const jwt = require("jsonwebtoken");
const WebSocket = require("ws");
const libData = require("@clusterio/lib/data");
const libErrors = require("@clusterio/lib/errors");
const { logger } = require("@clusterio/lib/logging");
const libPrometheus = require("@clusterio/lib/prometheus");
const lib = require("@clusterio/lib");
const { logger } = lib;
const ControlConnection = require("./ControlConnection");
const packageVersion = require("../package").version;
@@ -13,18 +11,18 @@ const HostConnection = require("./HostConnection");
const WsServerConnector = require("./WsServerConnector");
const wsMessageCounter = new libPrometheus.Counter(
const wsMessageCounter = new lib.Counter(
"clusterio_controller_websocket_message_total",
"How many messages have been received over WebSocket on the controller",
{ labels: ["direction"] }
);
const wsConnectionsCounter = new libPrometheus.Counter(
const wsConnectionsCounter = new lib.Counter(
"clusterio_controller_websocket_connections_total",
"How many WebSocket connections have been initiated on the controller"
);
const wsRejectedConnectionsCounter = new libPrometheus.Counter(
const wsRejectedConnectionsCounter = new lib.Counter(
"clusterio_controller_websocket_rejected_connections_total",
"How many WebSocket connections have been rejected during the handshake on the controller"
);
@@ -78,7 +76,7 @@ class WsServer {
try {
await task;
} catch (err) {
if (!(err instanceof libErrors.SessionLost)) {
if (!(err instanceof lib.SessionLost)) {
logger.warn(`Unexpected error disconnecting connector:\n${err.stack}`);
}
}
@@ -123,7 +121,7 @@ class WsServer {
loadedPlugins[name] = plugin.info.version;
}
socket.send(JSON.stringify(new libData.MessageHello(new libData.HelloData(packageVersion, loadedPlugins))));
socket.send(JSON.stringify(new lib.MessageHello(new lib.HelloData(packageVersion, loadedPlugins))));
this.attachHandler(socket, req);
}
@@ -160,8 +158,8 @@ ${err.stack}`
let message;
try {
const json = JSON.parse(rawMessage);
libData.Message.validate(json);
message = libData.Message.fromJSON(json);
lib.Message.validate(json);
message = lib.Message.fromJSON(json);
} catch (err) {
logger.verbose(`WsServer | closing ${req.socket.remoteAddress} after receiving invalid message`);
wsRejectedConnectionsCounter.inc();
@@ -239,7 +237,7 @@ ${err.stack}`
return;
}
let [connector, sessionToken] = this.createSession(new libData.Address(libData.Address.host, data.id));
let [connector, sessionToken] = this.createSession(new lib.Address(lib.Address.host, data.id));
let connection = this.hostConnections.get(data.id);
if (connection) {
logger.verbose(`WsServer | disconnecting existing connection for host ${data.id}`);
@@ -267,7 +265,7 @@ ${err.stack}`
});
this.hostConnections.set(data.id, connection);
this.controller.hostUpdated(this.controller.hosts.get(data.id));
let src = new libData.Address(libData.Address.host, data.id);
let src = new lib.Address(lib.Address.host, data.id);
connector.ready(socket, src, sessionToken);
}
@@ -298,7 +296,7 @@ ${err.stack}`
let id = this.nextControlId;
this.nextControlId += 1;
let [connector, sessionToken] = this.createSession(new libData.Address(libData.Address.control, id));
let [connector, sessionToken] = this.createSession(new lib.Address(lib.Address.control, id));
logger.verbose(`WsServer | registered control ${id} from ${req.socket.remoteAddress}`);
let connection = new ControlConnection(data, connector, this.controller, user, id);
@@ -306,7 +304,7 @@ ${err.stack}`
this.controlConnections.delete(id);
});
this.controlConnections.set(id, connection);
let account = new libData.AccountDetails(
let account = new lib.AccountDetails(
user.name,
[...user.roles].map(r => ({
name: r.name,
@@ -315,7 +313,7 @@ ${err.stack}`
}))
);
let src = new libData.Address(libData.Address.control, id);
let src = new lib.Address(lib.Address.control, id);
connector.ready(socket, src, sessionToken, account);
}
@@ -334,7 +332,7 @@ ${err.stack}`
}
} catch (err) {
socket.send(JSON.stringify(new libData.MessageInvalidate()));
socket.send(JSON.stringify(new lib.MessageInvalidate()));
this.attachHandler(socket, req);
return;
}
+11 -12
View File
@@ -1,20 +1,19 @@
"use strict";
const events = require("events");
const libData = require("@clusterio/lib/data");
const libLink = require("@clusterio/lib/link");
const { logger } = require("@clusterio/lib/logging");
const lib = require("@clusterio/lib");
const { logger } = lib;
/**
* Connector for controller connections
*
* @extends module:lib/link.WebSocketBaseConnector
* @extends module:lib.WebSocketBaseConnector
* @alias module:controller/src/WsServerConnector
*/
class WsServerConnector extends libLink.WebSocketBaseConnector {
class WsServerConnector extends lib.WebSocketBaseConnector {
constructor(dst, sessionId, sessionTimeout, heartbeatInterval) {
super(new libData.Address(libData.Address.controller, 0), dst);
super(new lib.Address(lib.Address.controller, 0), dst);
this._sessionTimeout = sessionTimeout;
this._socket = null;
@@ -40,16 +39,16 @@ class WsServerConnector extends libLink.WebSocketBaseConnector {
* Sends the ready message over the socket to initiate the session.
*
* @param {Object} socket - WebSocket connection to client.
* @param {module:lib/data.Address} src - Source address for this link.
* @param {module:lib.Address} src - Source address for this link.
* @param {string} sessionToken -
* the session token to send to the client.
* @param {module:lib/data.AccountDetails=} account -
* @param {module:lib.AccountDetails=} account -
* account data to provide to control connection
*/
ready(socket, src, sessionToken, account) {
this._socket = socket;
this._sendInternal(new libData.MessageReady(
new libData.ReadyData(
this._sendInternal(new lib.MessageReady(
new lib.ReadyData(
src,
sessionToken,
this._sessionTimeout,
@@ -89,8 +88,8 @@ class WsServerConnector extends libLink.WebSocketBaseConnector {
this._timeoutId = null;
}
this._sendInternal(new libData.MessageContinue(
new libData.ContinueData(this._sessionTimeout, this._heartbeatInterval, this._lastReceivedSeq)
this._sendInternal(new lib.MessageContinue(
new lib.ContinueData(this._sessionTimeout, this._heartbeatInterval, this._lastReceivedSeq)
));
this._state = "connected";
+2 -2
View File
@@ -1,9 +1,9 @@
// Shared metrics
"use strict";
const libPrometheus = require("@clusterio/lib/prometheus");
const lib = require("@clusterio/lib");
const util = require("util");
exports.endpointHitCounter = new libPrometheus.Counter(
exports.endpointHitCounter = new lib.Counter(
"clusterio_controller_http_endpoint_hits_total",
"How many requests a particular HTTP endpoint has gotten",
{ labels: ["route"], register: false }
+18 -25
View File
@@ -9,15 +9,8 @@ const path = require("path");
const nodeStream = require("stream");
const util = require("util");
const libData = require("@clusterio/lib/data");
const libErrors = require("@clusterio/lib/errors");
const libFileOps = require("@clusterio/lib/file_ops");
const libHash = require("@clusterio/lib/hash");
const libHelpers = require("@clusterio/lib/helpers");
const libLink = require("@clusterio/lib/link");
const libPlugin = require("@clusterio/lib/plugin");
const libPrometheus = require("@clusterio/lib/prometheus");
const { logger } = require("@clusterio/lib/logging");
const lib = require("@clusterio/lib");
const { logger } = lib;
const finished = util.promisify(nodeStream.finished);
@@ -40,7 +33,7 @@ function mergeSamples(destinationResult, sourceResult) {
// Prometheus polling endpoint
async function getMetrics(req, res, next) {
let results = [];
let pluginResults = await libPlugin.invokeHook(req.app.locals.controller.plugins, "onMetrics");
let pluginResults = await lib.invokeHook(req.app.locals.controller.plugins, "onMetrics");
for (let metricIterator of pluginResults) {
for await (let metric of metricIterator) {
results.push(metric);
@@ -53,9 +46,9 @@ async function getMetrics(req, res, next) {
if (!hostConnection.connected) {
continue;
}
requests.push(libHelpers.timeout(
hostConnection.send(new libData.HostMetricsRequest()).catch(err => {
if (!(err instanceof libErrors.SessionLost)) {
requests.push(lib.timeout(
hostConnection.send(new lib.HostMetricsRequest()).catch(err => {
if (!(err instanceof lib.SessionLost)) {
logger.error(`Unexpected error gathering metrics from host:\n${err.stack}`);
}
return null;
@@ -64,7 +57,7 @@ async function getMetrics(req, res, next) {
));
}
for await (let result of await libPrometheus.defaultRegistry.collect()) {
for await (let result of await lib.defaultRegistry.collect()) {
results.push(result);
}
@@ -87,12 +80,12 @@ async function getMetrics(req, res, next) {
}
for (let result of resultMap.values()) {
results.push(libPrometheus.deserializeResult(result));
results.push(lib.deserializeResult(result));
}
let text = await libPrometheus.exposition(results);
res.set("Content-Type", libPrometheus.exposition.contentType);
let text = await lib.exposition(results);
res.set("Content-Type", lib.exposition.contentType);
res.send(text);
}
@@ -227,12 +220,12 @@ async function uploadExport(req, res) {
}
let { name, ext } = path.posix.parse(filePath);
let hash = await libHash.hashStream(file.nodeStream());
let hash = await lib.hashStream(file.nodeStream());
assets[name] = `${name}.${hash}${ext}`;
await libFileOps.safeOutputFile(path.join("static", `${name}.${hash}${ext}`), await file.async("nodebuffer"));
await lib.safeOutputFile(path.join("static", `${name}.${hash}${ext}`), await file.async("nodebuffer"));
}
modPack.exportManifest = new libData.ExportManifest(assets);
modPack.exportManifest = new lib.ExportManifest(assets);
modPack.fillDefaultSettings(settingPrototypes, logger);
res.app.locals.controller.modPackUpdated(modPack);
@@ -363,7 +356,7 @@ async function uploadSave(req, res) {
try {
let storedName = await Promise.race([
req.app.locals.controller.sendToHostByInstanceId(
new libData.InstancePullSaveRequest(
new lib.InstancePullSaveRequest(
instanceId,
proxyStream.id,
filename,
@@ -462,9 +455,9 @@ async function uploadSave(req, res) {
function checkModName(name) {
try {
libFileOps.checkFilename(name);
lib.checkFilename(name);
} catch (err) {
throw new libErrors.RequestError(`Mod name ${err.message}`);
throw new lib.RequestError(`Mod name ${err.message}`);
}
}
@@ -512,7 +505,7 @@ async function uploadMod(req, res) {
break;
} catch (err) {
if (err.code === "EEXIST") {
tempFilename = await libFileOps.findUnusedName(modsDirectory, tempFilename, ".tmp.zip");
tempFilename = await lib.findUnusedName(modsDirectory, tempFilename, ".tmp.zip");
} else {
throw err;
}
@@ -521,7 +514,7 @@ async function uploadMod(req, res) {
stream.pipe(writeStream);
await finished(writeStream);
const modInfo = await libData.ModInfo.fromModFile(path.join(modsDirectory, tempFilename));
const modInfo = await lib.ModInfo.fromModFile(path.join(modsDirectory, tempFilename));
await fs.rename(path.join(modsDirectory, tempFilename), path.join(modsDirectory, modInfo.filename));
req.app.locals.controller.mods.set(modInfo.filename, modInfo);
req.app.locals.controller.modUpdated(modInfo);