const Redis = require('../../../lib/ioredis-cluster')
module.exports = async (options) => {
const { socket } = options;
try {
let redisConfig = options.payload.model;
const actualConnection = p3xrs.connections.list.find(con => redisConfig.id === con.id)
if (actualConnection !== undefined) {
if (redisConfig.password === actualConnection.id) {
redisConfig.password = actualConnection.password;
}
if (redisConfig.tlsCrt === actualConnection.id) {
redisConfig.tlsCrt = actualConnection.tlsCrt;
}
if (redisConfig.tlsKey === actualConnection.id) {
redisConfig.tlsKey = actualConnection.tlsKey;
}
if (redisConfig.tlsCa === actualConnection.id) {
redisConfig.tlsCa = actualConnection.tlsCa;
}
if (redisConfig.sshPassword === actualConnection.id) {
redisConfig.sshPassword = actualConnection.sshPassword;
}
if (redisConfig.sshPrivateKey === actualConnection.id) {
redisConfig.sshPrivateKey = actualConnection.sshPrivateKey;
}
}
const sentinelName = redisConfig.sentinelName
//TODO fix secured nodes password
delete redisConfig.name
delete redisConfig.id
if (redisConfig.tlsWithoutCert) {
redisConfig.tls = {
}
} else if (typeof redisConfig.tlsCa === 'string' && redisConfig.tlsCa.trim() !== '') {
redisConfig.tls = {
//rejectUnauthorized: false,
cert: redisConfig.tlsCrt,
key: redisConfig.tlsKey,
ca: redisConfig.tlsCa,
}
}
if (redisConfig.hasOwnProperty('tls')) {
redisConfig.tls.rejectUnauthorized = redisConfig.tlsRejectUnauthorized === undefined ? false : redisConfig.tlsRejectUnauthorized
}
if (redisConfig.hasOwnProperty('sentinel') && redisConfig.sentinel === true) {
redisConfig.nodes = redisConfig.nodes.map((node) => {
if (node.password === node.id) {
const foundNode = actualConnection.nodes.find((findNode) => findNode.id === node.password)
node.password = foundNode.password
}
return node
})
redisConfig = [redisConfig].concat(redisConfig.nodes)
} else if (redisConfig.cluster === true) {
redisConfig.nodes = redisConfig.nodes.map((node) => {
if (node.password === node.id) {
const foundNode = actualConnection.nodes.find((findNode) => findNode.id === node.password)
node.password = foundNode.password
}
return node
})
redisConfig = [redisConfig].concat(redisConfig.nodes)
}
if (Array.isArray(redisConfig) && redisConfig[0].hasOwnProperty('sentinel') && redisConfig[0].sentinel === true) {
redisConfig = {
sentinels: redisConfig,
name: sentinelName,
sentinelPassword: redisConfig[0].password,
sentinelRetryStrategy: () => {
return false
}
}
}
let ssh = undefined
if (!Array.isArray(redisConfig)) {
if (redisConfig.ssh === true) {
const { NodeSSH } = require('node-ssh');
const getPort = require('get-port');
ssh = new NodeSSH();
const sshOptions = {
host: redisConfig.sshHost,
port: parseInt(redisConfig.sshPort, 10),
username: redisConfig.sshUsername,
...(redisConfig.sshPrivateKey
? { privateKey: redisConfig.sshPrivateKey }
: { password: redisConfig.sshPassword }),
};
try {
console.log('Connecting to SSH server...');
await ssh.connect(sshOptions);
console.log('SSH connection established.');
// Dynamically get an available local port
const localPort = await getPort.default();
console.log(`Dynamic local port allocated: ${localPort}`);
// Manually set up port forwarding
const forwardCommand = `ssh -L 127.0.0.1:${localPort}:${redisConfig.host}:${redisConfig.port} -N`;
const result = await ssh.execCommand(forwardCommand, { execOptions: { pty: true } });
if (result.stderr) {
throw new Error(`Failed to forward port: ${result.stderr}`);
}
console.log('Port forwarding set up successfully.');
// Update redisConfig with the dynamically assigned port
//redisConfig.port = localPort;
// Assign the SSH connection as tunnel and client
console.log(`Tunnel created on local port: ${localPort}`);
} catch (error) {
console.error('Failed to set up SSH tunnel:', error);
socket.emit(options.responseEvent, {
status: 'error',
error: error.message,
});
}
}
}
let redis = new Redis(redisConfig)
//console.info('redis-test-connection', redisConfig)
redis.on('error', function (error) {
console.error(error)
socket.emit(options.responseEvent, {
status: 'error',
error: error.message
})
redis.disconnect()
if (ssh && ssh.connection) {
ssh.connection.end()
}
})
redis.on('connect', async function () {
try {
//await redis.call('client', 'list')
setTimeout(() => {
socket.emit(options.responseEvent, {
status: 'ok',
})
}, 1000)
} catch (error) {
console.error(error)
socket.emit(options.responseEvent, {
status: 'error',
error: error.message
})
} finally {
redis.disconnect()
if (ssh && ssh.connection) {
ssh.connection.end()
}
}
})
} catch (e) {
console.error(e)
socket.emit(options.responseEvent, {
status: 'error',
error: e.message
})
}
}