Skip to content

Commit 5f7fc33

Browse files
authored
CSHARP-4718: Enable Container and kubernetes awareness (#1295)
1 parent 43fb293 commit 5f7fc33

File tree

4 files changed

+141
-1
lines changed

4 files changed

+141
-1
lines changed

src/MongoDB.Driver.Core/Core/Connections/ClientDocumentHelper.cs

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
using System.Text.RegularExpressions;
2020
using MongoDB.Bson;
2121
using MongoDB.Driver.Core.Configuration;
22+
using MongoDB.Driver.Core.Misc;
2223

2324
namespace MongoDB.Driver.Core.Connections
2425
{
@@ -30,17 +31,31 @@ internal class ClientDocumentHelper
3031
private static Lazy<BsonDocument> __envDocument;
3132
private static Lazy<BsonDocument> __osDocument;
3233
private static Lazy<string> __platformString;
34+
private static IEnvironmentVariableProvider __environmentVariableProvider;
35+
private static IFileSystemProvider __fileSystemProvider;
3336

3437
private static void Initialize()
3538
{
3639
__driverDocument = new Lazy<BsonDocument>(CreateDriverDocument);
3740
__envDocument = new Lazy<BsonDocument>(CreateEnvDocument);
3841
__osDocument = new Lazy<BsonDocument>(CreateOSDocument);
3942
__platformString = new Lazy<string>(GetPlatformString);
43+
__environmentVariableProvider = EnvironmentVariableProvider.Instance;
44+
__fileSystemProvider = FileSystemProvider.Instance;
4045
}
4146

4247
static ClientDocumentHelper() => Initialize();
4348

49+
internal static void SetEnvironmentVariableProvider(IEnvironmentVariableProvider environmentVariableProvider)
50+
{
51+
__environmentVariableProvider = environmentVariableProvider;
52+
}
53+
54+
internal static void SetFileSystemProvider(IFileSystemProvider fileSystemProvider)
55+
{
56+
__fileSystemProvider = fileSystemProvider;
57+
}
58+
4459
// private static methods
4560
internal static BsonDocument CreateClientDocument(string applicationName, LibraryInfo libraryInfo)
4661
{
@@ -107,13 +122,15 @@ internal static BsonDocument CreateEnvDocument()
107122
var timeout = GetTimeoutSec(name);
108123
var memoryDb = GetMemoryMb(name);
109124
var region = GetRegion(name);
125+
var container = GetContainerDocument();
110126

111127
return new BsonDocument
112128
{
113129
{ "name", name },
114130
{ "timeout_sec", timeout, timeout.HasValue },
115131
{ "memory_mb", memoryDb, memoryDb.HasValue },
116-
{ "region", region, region != null }
132+
{ "region", region, region != null },
133+
{ "container", container, container != null }
117134
};
118135
}
119136
else
@@ -176,6 +193,23 @@ string GetRegion(string name) =>
176193
_ => null,
177194
};
178195

196+
BsonDocument GetContainerDocument()
197+
{
198+
var isExecutionContainerDocker = __fileSystemProvider.File.Exists("/.dockerenv");
199+
var isOrchestratorKubernetes = __environmentVariableProvider.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST") != null;
200+
201+
if (isExecutionContainerDocker || isOrchestratorKubernetes)
202+
{
203+
return new()
204+
{
205+
{ "runtime", "docker", isExecutionContainerDocker },
206+
{ "orchestrator", "kubernetes", isOrchestratorKubernetes }
207+
};
208+
}
209+
210+
return null;
211+
}
212+
179213
int? GetIntValue(string environmentVariable) =>
180214
int.TryParse(Environment.GetEnvironmentVariable(environmentVariable), out var value) ? value : null;
181215
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
namespace MongoDB.Driver.Core.Misc
17+
{
18+
/// <summary>
19+
/// Abstractions of the file system.
20+
/// </summary>
21+
internal interface IFileSystemProvider
22+
{
23+
IFile File { get; }
24+
}
25+
26+
internal class FileSystemProvider : IFileSystemProvider
27+
{
28+
public static IFileSystemProvider Instance { get; } = new FileSystemProvider();
29+
public IFile File { get; } = new FileWrapper();
30+
}
31+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/* Copyright 2010-present MongoDB Inc.
2+
*
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
16+
using System.IO;
17+
18+
namespace MongoDB.Driver.Core.Misc
19+
{
20+
/// <summary>
21+
/// Abstraction for static methods in <see cref="System.IO.File" />.
22+
/// </summary>
23+
internal interface IFile
24+
{
25+
bool Exists(string name);
26+
}
27+
28+
internal sealed class FileWrapper : IFile
29+
{
30+
public bool Exists(string name)
31+
{
32+
return File.Exists(name);
33+
}
34+
}
35+
}

tests/MongoDB.Driver.Core.Tests/Core/Connections/ClientDocumentHelperTests.cs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,9 @@
1919
using MongoDB.Bson;
2020
using MongoDB.Driver.Core.TestHelpers;
2121
using MongoDB.Driver.Core.Configuration;
22+
using MongoDB.Driver.Core.Misc;
2223
using MongoDB.TestHelpers.XunitExtensions;
24+
using Moq;
2325
using Xunit;
2426

2527
namespace MongoDB.Driver.Core.Connections
@@ -132,6 +134,44 @@ public void CreateDriverDocument_with_args_should_return_expected_result(
132134
result.Should().Be($"{{ name : 'mongo-csharp-driver', version : '{driverVersion}' }}");
133135
}
134136

137+
[Theory]
138+
[InlineData(true, true, "{ name : 'vercel', container : { \"runtime\" : \"docker\", \"orchestrator\" : \"kubernetes\" }}")]
139+
[InlineData(false, true, "{ name : 'vercel', container : { \"orchestrator\" : \"kubernetes\" }}")]
140+
[InlineData(true, false, "{ name : 'vercel', container : { \"runtime\" : \"docker\" }}")]
141+
[InlineData(false, false, "{ name : 'vercel' }")]
142+
public void CreateEnvDocument_should_return_expected_result(bool isDockerToBeDetected, bool isKubernetesToBeDetected, string expected)
143+
{
144+
var fileSystemProviderMock = new Mock<IFileSystemProvider>();
145+
var environmentVariableProviderMock = new Mock<IEnvironmentVariableProvider>();
146+
147+
if (isKubernetesToBeDetected)
148+
{
149+
environmentVariableProviderMock.Setup(p => p.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST")).Returns("dummy");
150+
}
151+
else
152+
{
153+
environmentVariableProviderMock.Setup(p => p.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST")).Returns(null as string);
154+
}
155+
156+
if (isDockerToBeDetected)
157+
{
158+
fileSystemProviderMock.Setup(p => p.File.Exists("/.dockerenv")).Returns(true);
159+
}
160+
else
161+
{
162+
fileSystemProviderMock.Setup(p => p.File.Exists("/.dockerenv")).Returns(false);
163+
164+
}
165+
166+
ClientDocumentHelper.SetEnvironmentVariableProvider(environmentVariableProviderMock.Object);
167+
ClientDocumentHelper.SetFileSystemProvider(fileSystemProviderMock.Object);
168+
using (new DisposableEnvironmentVariable("VERCEL"))
169+
{
170+
var result = ClientDocumentHelper.CreateEnvDocument();
171+
result.Should().Be(expected);
172+
}
173+
}
174+
135175
[Fact]
136176
public void CreateOSDocument_should_return_expected_result()
137177
{

0 commit comments

Comments
 (0)