Skip to content

Commit 22b07d8

Browse files
gribnoysupaddaleax
andauthored
fix(cli-repl): Detect containerized environment and disable telemetry MONGOSH-1278 (#1326)
* fix(cli-repl): Detect containerized environment and disable telemetry MONGOSH-1278 * test(cli-repl): Add tests for telemetry disabling * fix(cli-repl): Explicit return types and stricter regexp Co-authored-by: Anna Henningsen <[email protected]> Co-authored-by: Anna Henningsen <[email protected]>
1 parent 567160b commit 22b07d8

File tree

4 files changed

+59
-3
lines changed

4 files changed

+59
-3
lines changed

package-lock.json

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/cli-repl/src/cli-repl.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,18 @@ describe('CliRepl', () => {
946946
expect(requests).to.have.lengthOf(2);
947947
});
948948

949+
it('sends out telemetry if the repl is running in an interactive mode in a containerized environment', async() => {
950+
cliRepl = new CliRepl(cliReplOptions);
951+
cliRepl.getIsContainerizedEnvironment = () => {
952+
return Promise.resolve(true);
953+
};
954+
await cliRepl.start(await testServer.connectionString(), {});
955+
input.write('db.hello()\n');
956+
input.write('exit\n');
957+
await waitBus(cliRepl.bus, 'mongosh:closed');
958+
expect(requests).to.have.lengthOf(2);
959+
});
960+
949961
it('does not send out telemetry if the user starts with a no-telemetry config', async() => {
950962
await fs.writeFile(path.join(tmpdir.path, 'config'), EJSON.stringify({ enableTelemetry: false }));
951963
await cliRepl.start(await testServer.connectionString(), {});
@@ -986,6 +998,19 @@ describe('CliRepl', () => {
986998
expect(requests).to.have.lengthOf(0);
987999
});
9881000

1001+
it('does not send out telemetry if the repl is running in non-interactive mode in a containerized environment', async() => {
1002+
cliReplOptions.shellCliOptions.eval = ['db.hello()'];
1003+
cliRepl = new CliRepl(cliReplOptions);
1004+
cliRepl.getIsContainerizedEnvironment = () => {
1005+
return Promise.resolve(true);
1006+
};
1007+
await startWithExpectedImmediateExit(
1008+
cliRepl,
1009+
await testServer.connectionString()
1010+
);
1011+
expect(requests).to.have.lengthOf(0);
1012+
});
1013+
9891014
context('with a 5.0+ server', () => {
9901015
skipIfServerVersion(testServer, '<= 4.4');
9911016

packages/cli-repl/src/cli-repl.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ class CliRepl implements MongoshIOProvider {
9595
warnedAboutInaccessibleFiles = false;
9696
onExit: (code?: number) => Promise<never>;
9797
closing = false;
98+
isContainerizedEnvironment = false;
9899

99100
/**
100101
* Instantiate the new CLI Repl.
@@ -155,6 +156,29 @@ class CliRepl implements MongoshIOProvider {
155156
});
156157
}
157158

159+
async getIsContainerizedEnvironment() {
160+
// Check for dockerenv file first
161+
try {
162+
await fs.stat('/.dockerenv');
163+
return true;
164+
} catch {
165+
try {
166+
// Check if there is any mention of docker / lxc / k8s in control groups
167+
const cgroup = await fs.readFile('/proc/self/cgroup', 'utf8');
168+
return /\b(docker|lxc|kubepods)\b/.test(cgroup);
169+
} catch {
170+
return false;
171+
}
172+
}
173+
}
174+
175+
get forceDisableTelemetry(): boolean {
176+
return (
177+
this.globalConfig?.forceDisableTelemetry ||
178+
(this.isContainerizedEnvironment && !this.mongoshRepl.isInteractive)
179+
);
180+
}
181+
158182
/**
159183
* Setup CLI environment: serviceProvider, ShellEvaluator, log connection
160184
* information, external editor, and finally start the repl.
@@ -167,6 +191,9 @@ class CliRepl implements MongoshIOProvider {
167191
const { version } = require('../package.json');
168192
await this.verifyNodeVersion();
169193

194+
this.isContainerizedEnvironment =
195+
await this.getIsContainerizedEnvironment();
196+
170197
if (!this.cliOptions.nodb) {
171198
const cs = new ConnectionString(driverUri);
172199
const searchParams = cs.typedSearchParams<DevtoolsConnectOptions>();
@@ -215,7 +242,8 @@ class CliRepl implements MongoshIOProvider {
215242
this.toggleableAnalytics,
216243
{
217244
platform: process.platform,
218-
arch: process.arch
245+
arch: process.arch,
246+
is_containerized: this.isContainerizedEnvironment,
219247
},
220248
require('../package.json').version);
221249

@@ -329,7 +357,7 @@ class CliRepl implements MongoshIOProvider {
329357
// case.
330358
return;
331359
}
332-
if (enabled && !this.globalConfig.forceDisableTelemetry) {
360+
if (enabled && !this.forceDisableTelemetry) {
333361
this.toggleableAnalytics.enable();
334362
} else {
335363
this.toggleableAnalytics.disable();

packages/cli-repl/src/mongosh-repl.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -167,6 +167,10 @@ class MongoshNodeRepl implements EvaluationListener {
167167
this.runtimeState().instanceState.isInteractive = value;
168168
}
169169

170+
get isInteractive(): boolean {
171+
return this.runtimeState().instanceState.isInteractive;
172+
}
173+
170174
/**
171175
* Create a Node.js REPL instance that can run mongosh commands,
172176
* print greeting messages, and set up autocompletion and

0 commit comments

Comments
 (0)