Repository navigation
Migration: route execution and validation through the SSH tunnel for tunnelled connections #573
Description
Problem
Raised by @jamby77 on #572. Migration execution (all three modes) and validation build their clients from connectionRegistry.getConfig(), which returns the stored host and port:
apps/api/src/migration/execution/client-factory.tspassesconfig.host/config.portto iovalkey forcommandmode and for validation.apps/api/src/migration/execution/toml-builder.tswrites the same host and port into the RedisShake TOML forredis_shakeandredis_shake_sync.
For a connection with sshTunnel set, the registry's own adapter talks to 127.0.0.1:<localPort> opened by SshTunnelService, but the migration clients dial the remote address directly. If the BetterDB host cannot reach that address (the usual reason for a tunnel), execution and validation fail to connect while analysis, which goes through the adapter, works. assertLiveMigrationPair in live-connections.ts does not reject the case, so the user gets a connection error at run time rather than a clear message up front.
Docs now state the limitation (#572). This issue is the fix for the tunnel half.
Proposal
- Add a helper, e.g.
resolveMigrationEndpoint(connectionId)on the registry or a small service, that returns{ host, port, tls, username, password }for migration use: for a tunnelled connection, ensure the tunnel is up viaSshTunnelServiceand return127.0.0.1plus itslocalPort; otherwise return the stored values. - Use it in
migration-execution.service.ts(both the TOML builders andrunCommandMode) and inmigration-validation.service.tsinstead ofgetConfig()for host and port. Credentials and TLS still come from the stored config. - Keep the tunnel alive for the life of the job. The tunnel service may close idle tunnels; the execution job should hold a reference (or ping through it) until the job is terminal, and release it in the existing
finallycleanup. - Cluster sources through a tunnel remain unsupported for the RedisShake modes and for the per-master fan-out in command mode, for the same reason as the monitoring limitation in the README: nodes advertise their own addresses. Reject that combination in
assertLiveMigrationPairwith a message saying so, instead of failing mid-run. - TLS: RedisShake and iovalkey will connect to
127.0.0.1withtls = trueand the certificate will not match. Either passservernamethrough for iovalkey and check what RedisShake supports, or document that tunnelled TLS sources need the tunnel to terminate TLS.
Out of scope
Agent connections (host === 'agent'). The agent carries commands over a WebSocket and has no TCP endpoint, so RedisShake cannot use it. command mode could in principle run through the agent adapter instead of a raw iovalkey client, but that is a different change. For now assertLiveMigrationPair should reject agent connections for execution with a clear message, which can be done in this issue since it is one line.
Tests
- Unit test for the endpoint resolver with and without
sshTunnel. - A migration e2e variant that puts the source behind a local SSH container (the sentinel e2e compose already has the pattern for a jump host, if not,
linuxserver/openssh-serveris enough).
Activity