Skip to content

Commit 50c915f

Browse files
authored
fix(service-provider-core): allow specifying a --port for a seed list MONGOSH-939 (#1054)
1 parent 4a4cbc4 commit 50c915f

File tree

3 files changed

+58
-2
lines changed

3 files changed

+58
-2
lines changed

packages/i18n/src/locales/en_US.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ const translations: Catalog = {
8585
'uri-generator': {
8686
'no-host-port': 'If a full URI is provided, you cannot also specify --host or --port',
8787
'invalid-host': 'The --host argument contains an invalid character',
88+
'host-list-port-mismatch': 'The host list contains different ports than provided by --port',
8889
'diverging-service-name': 'Either the --gssapiServiceName parameter or the SERVICE_NAME authentication mechanism property in the connection string can be used but not both.',
8990
'gssapi-service-name-unsupported': 'The gssapiServiceName query parameter is not supported anymore. Please use the --gssapiServiceName argument or the SERVICE_NAME authentication mechanism property (e.g. ?authMechanismProperties=SERVICE_NAME:<value>).',
9091
}

packages/service-provider-core/src/uri-generator.spec.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -423,14 +423,34 @@ describe('uri-generator.generate-uri', () => {
423423
const options = { host: 'host1:123,host2,host3:456,' };
424424
expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/');
425425
});
426+
426427
it('returns a URI for the hosts and ports specified in --host and database name', () => {
427428
const options = {
428429
host: 'host1:123,host_2,host3:456,',
429430
connectionSpecifier: 'admin'
430431
};
431432
expect(generateUri(options)).to.equal('mongodb://host1:123,host_2,host3:456/admin');
432433
});
434+
435+
it('returns a URI for the hosts in --host and fixed --port', () => {
436+
const options = {
437+
host: 'host1:1234,host_2',
438+
port: '1234',
439+
connectionSpecifier: 'admin'
440+
};
441+
expect(generateUri(options)).to.equal('mongodb://host1:1234,host_2:1234/admin');
442+
});
443+
444+
it('throws an error if seed list in --host contains port mismatches from fixed --port', () => {
445+
const options = {
446+
host: 'host1,host_2:123',
447+
port: '1234',
448+
connectionSpecifier: 'admin'
449+
};
450+
expect(() => generateUri(options)).to.throw('The host list contains different ports than provided by --port');
451+
});
433452
});
453+
434454
context('with a replica set', () => {
435455
it('returns a URI for the hosts and ports specified in --host', () => {
436456
const options = { host: 'replsetname/host1:123,host2,host3:456,' };
@@ -446,6 +466,16 @@ describe('uri-generator.generate-uri', () => {
446466
const options = { host: 'replsetname/host1:123,host2,host3:456', connectionSpecifier: 'admin?foo=bar' };
447467
expect(generateUri(options)).to.equal('mongodb://host1:123,host2,host3:456/admin%3Ffoo%3Dbar?replicaSet=replsetname');
448468
});
469+
470+
it('returns a URI for the hosts specified in --host and explicit --port', () => {
471+
const options = { host: 'replsetname/host1:123,host2,', port: '123' };
472+
expect(generateUri(options)).to.equal('mongodb://host1:123,host2:123/?replicaSet=replsetname');
473+
});
474+
475+
it('throws an error if the hosts contain ports that mismatch from --port', () => {
476+
const options = { host: 'replsetname/host1:1234,host2,', port: '123' };
477+
expect(() => generateUri(options)).to.throw('The host list contains different ports than provided by --port');
478+
});
449479
});
450480
});
451481
});

packages/service-provider-core/src/uri-generator.ts

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,11 @@ const CONFLICT = 'cli-repl.uri-generator.no-host-port';
3434
*/
3535
const INVALID_HOST = 'cli-repl.uri-generator.invalid-host';
3636

37+
/**
38+
* Host seed list contains a port that mismatches an explicit --port.
39+
*/
40+
const HOST_LIST_PORT_MISMATCH = 'cli-repl.uri-generator.host-list-port-mismatch';
41+
3742
/**
3843
* Diverging gssapiServiceName and SERVICE_NAME mechanism property
3944
*/
@@ -79,6 +84,26 @@ function validateHost(host: string): void {
7984
}
8085
}
8186

87+
/**
88+
* Validates a host seed list against a specified fixed port and
89+
* returns an individual `<host>:<port>` array.
90+
*/
91+
function validateHostSeedList(hosts: string, fixedPort: string | undefined): string[] {
92+
const trimmedHosts = hosts.split(',').map(h => h.trim()).filter(h => !!h);
93+
const hostList: string[] = [];
94+
trimmedHosts.forEach(h => {
95+
const [host, port] = h.split(':');
96+
if (fixedPort && port !== undefined && port !== fixedPort) {
97+
throw new MongoshInvalidInputError(
98+
i18n.__(HOST_LIST_PORT_MISMATCH),
99+
CommonErrors.InvalidArgument
100+
);
101+
}
102+
hostList.push(`${host}${(port || fixedPort) ? ':' + (port || fixedPort) : ''}`);
103+
});
104+
return hostList;
105+
}
106+
82107
/**
83108
* Generate the host from the options or default.
84109
*
@@ -154,7 +179,7 @@ function generateUriNormalized(options: CliOptions): ConnectionString {
154179
if (replSetHostMatch) {
155180
const { replSetName, hosts } = replSetHostMatch.groups as { replSetName: string, hosts: string };
156181
const connectionString = new ConnectionString(`${Scheme.Mongo}replacemeHost/${encodeURIComponent(uri || '')}`);
157-
connectionString.hosts = hosts.split(',').filter(host => host.trim());
182+
connectionString.hosts = validateHostSeedList(hosts, options.port);
158183
connectionString.searchParams.set('replicaSet', replSetName);
159184
return addShellConnectionStringParameters(connectionString);
160185
}
@@ -167,7 +192,7 @@ function generateUriNormalized(options: CliOptions): ConnectionString {
167192
if (seedList && options.host?.includes(',')) {
168193
const { hosts } = seedList.groups as { hosts: string };
169194
const connectionString = new ConnectionString(`${Scheme.Mongo}replacemeHost/${encodeURIComponent(uri || '')}`);
170-
connectionString.hosts = hosts.split(',').filter(host => host.trim());
195+
connectionString.hosts = validateHostSeedList(hosts, options.port);
171196
return addShellConnectionStringParameters(connectionString);
172197
}
173198

0 commit comments

Comments
 (0)