Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion server/app/core/sshManager.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,5 +247,6 @@ module.exports = {
getSshHostinfo,
removeSsh,
askPassword,
createSsh
createSsh,
isVerboseSshEnabled
};
2 changes: 1 addition & 1 deletion server/app/db/version.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"version": "2026-0605-211714" }
{"version": "2026-0605-221627" }
13 changes: 11 additions & 2 deletions server/app/handlers/tryToConnect.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,19 @@ const SshClientWrapper = require("ssh-client-wrapper");
const { getLogger } = require("../logSettings");
const logger = getLogger();
const { remoteHost } = require("../db/db");
const { askPassword } = require("../core/sshManager.js");
const { askPassword, isVerboseSshEnabled } = require("../core/sshManager.js");

/**
* try to connect remote host via ssh
* @param {string} clientID - socketIO client's ID string
* @param {object} hostInfo - target host's information
* @param {Function} cb - call back function called with string "success" or "error"
* @returns {Promise<void>}
*/
async function onTryToConnect(clientID, hostInfo, cb) {
hostInfo.password = askPassword.bind(null, clientID, hostInfo.name, "password", null);
hostInfo.passphrase = askPassword.bind(null, clientID, hostInfo.name, "passphrase", null);
if (process.env.WHEEL_VERBOSE_SSH) {
if (isVerboseSshEnabled()) {
hostInfo.sshOpt = ["-vvv"];
}
const ssh = new SshClientWrapper(hostInfo);
Expand All @@ -38,6 +39,14 @@ async function onTryToConnect(clientID, hostInfo, cb) {
ssh.disconnect();
return cb("success");
}

/**
* try to connect remote host via ssh with host id
* @param {string} clientID - socketIO client's ID string
* @param {string} id - remote host id
* @param {Function} cb - call back function called with string "success" or "error"
* @returns {Promise<void>}
*/
async function onTryToConnectById(clientID, id, cb) {
const hostInfo = remoteHost.get(id);
await onTryToConnect(clientID, hostInfo, cb);
Expand Down
108 changes: 108 additions & 0 deletions server/test/app/handlers/tryToConnect.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
"use strict";
const os = require("os");
const path = require("path");
const fs = require("fs-extra");

const chai = require("chai");
const expect = chai.expect;
const sinon = require("sinon");
chai.use(require("sinon-chai"));
const rewire = require("rewire");

describe("tryToConnect UT", ()=>{
const originalHome = process.env.HOME;
const originalWheelUseHttp = process.env.WHEEL_USE_HTTP;
const originalWheelVerboseSsh = process.env.WHEEL_VERBOSE_SSH;
let tempHome;
let tryToConnect;
let onTryToConnect;
let SshClientWrapperMock;
let canConnectMock;
let disconnectMock;
let askPasswordMock;
let cb;

before(async ()=>{
tempHome = await fs.mkdtemp(path.join(os.tmpdir(), "wheel-try-connect-"));
process.env.HOME = tempHome;
process.env.WHEEL_USE_HTTP = "1";
await fs.ensureDir(path.join(tempHome, ".wheel"));
await Promise.all([
fs.writeJson(path.join(tempHome, ".wheel", "remotehost.json"), []),
fs.writeJson(path.join(tempHome, ".wheel", "projectList.json"), []),
fs.writeJson(path.join(tempHome, ".wheel", "jobScriptTemplate.json"), [])
]);
});

beforeEach(()=>{
cb = sinon.stub();
canConnectMock = sinon.stub().resolves();
disconnectMock = sinon.stub();
askPasswordMock = sinon.stub();

tryToConnect = rewire("../../../app/handlers/tryToConnect.js");
SshClientWrapperMock = sinon.stub().callsFake((hostInfo)=>{
return {
hostInfo,
canConnect: canConnectMock,
disconnect: disconnectMock
};
});

tryToConnect.__set__({
SshClientWrapper: SshClientWrapperMock,
askPassword: askPasswordMock,
logger: {
debug: sinon.stub(),
info: sinon.stub(),
error: sinon.stub()
}
});
onTryToConnect = tryToConnect.__get__("onTryToConnect");
});

afterEach(()=>{
sinon.restore();
if (originalWheelVerboseSsh !== undefined) {
process.env.WHEEL_VERBOSE_SSH = originalWheelVerboseSsh;
} else {
delete process.env.WHEEL_VERBOSE_SSH;
}
});

after(async ()=>{
if (originalHome !== undefined) {
process.env.HOME = originalHome;
} else {
delete process.env.HOME;
}
if (originalWheelUseHttp !== undefined) {
process.env.WHEEL_USE_HTTP = originalWheelUseHttp;
} else {
delete process.env.WHEEL_USE_HTTP;
}
await fs.remove(tempHome);
});

it("should set sshOpt when WHEEL_VERBOSE_SSH is truthy", async ()=>{
process.env.WHEEL_VERBOSE_SSH = "true";
const hostInfo = { name: "testHost", host: "localhost", port: 22, user: "test" };

await onTryToConnect("client-1", hostInfo, cb);

expect(hostInfo.sshOpt).to.deep.equal(["-vvv"]);
expect(SshClientWrapperMock).to.have.been.calledOnceWithExactly(hostInfo);
expect(cb).to.have.been.calledOnceWithExactly("success");
});

it("should not set sshOpt when WHEEL_VERBOSE_SSH is false-like", async ()=>{
process.env.WHEEL_VERBOSE_SSH = "false";
const hostInfo = { name: "testHost", host: "localhost", port: 22, user: "test" };

await onTryToConnect("client-1", hostInfo, cb);

expect(hostInfo).to.not.have.property("sshOpt");
expect(SshClientWrapperMock).to.have.been.calledOnceWithExactly(hostInfo);
expect(cb).to.have.been.calledOnceWithExactly("success");
});
});
Loading